简介::将下面第一段代码中的原始指针转换为智能指针,而其余功能保留为 尽可能保持不变。
我正在编写一些代码,试图将指针传递给对象的构造函数,目的是在构造函数返回时使该指针指向构造的对象。
(注意:这起源于一个更为复杂的情况,但我已将其简化为问题的本质。因此,如果您尝试询问为什么我正在这样做,在这种情况下不一定会找到明智的答案-但这不是问题的重点。)
在努力使用智能指针实现之后,我恢复了原始指针以确保没有遗漏一个基本问题:
#include <iostream>
class Thing {
public:
Thing(int data, Thing* thing_ptr) {
data_ = data;
*thing_ptr = *this;
}
void PrintData() {
std::cout << data_ << std::endl;
}
private:
int data_;
};
int main() {
Thing* thing_ptr;
Thing t(6, thing_ptr);
thing_ptr->PrintData();
return 0;
}
顺利进行了,但是当我返回智能指针时,我似乎无法重现此功能。基本的问题是我不执行不必要的额外工作或无法正常工作,不知道如何初始化智能指针。
我尝试的第一件事是:
#include <iostream>
#include <memory>
class Thing {
public:
Thing(int data, std::unique_ptr<Thing>& thing_ptr) {
data_ = data;
thing_ptr = std::unique_ptr<Thing>(this);
}
void PrintData() {
std::cout << data_ << std::endl;
}
private:
int data_;
};
int main() {
std::unique_ptr<Thing> thing_ptr;
Thing th(6, thing_ptr);
thing_ptr->PrintData();
return 0;
}
我认为失败了(运行时发生核心转储),因为 this
实际上不是指向Thing
的指针,而是指向未初始化的内存块的指针。容纳Thing
的正确大小。实际上,我不是100%知道这里发生了什么,但是由于unique_ptr
和shared_ptr
都失败了,我决定我应该首先初始化智能指针,然后分配 {{1} } 。
问题是我无法用这种方法创建一个额外的对象(这反过来甚至需要添加一个额外的构造函数)。
this
在这里我做一个 Thing() : data_(0) {}
Thing(int data, std::unique_ptr<Thing>& thing_ptr) {
data_ = data;
if (!thing_ptr) {
thing_ptr = std::make_unique<Thing>();
}
*thing_ptr = *this;
}
只是将其分配给下一行,这肯定不是正确的方法。
聪明的人可以向我指出正确的方向吗?
答案 0 :(得分:3)
智能指针的最常见用法是管理对象的生存期。但是请注意,当您声明具有类类型的变量时,如
Thing th(6, thing_ptr);
对于该对象的生存期别无选择:如果在功能块中声明,它将在下一个封闭的}
处结束,或者如果声明为类成员,则在包含对象的生存期结束时结束,如果声明为名称空间成员,则在程序末尾。 std::unique_ptr<T>
使用默认删除器只能包含指向使用new
创建的对象的指针,因为默认删除器会尝试使用delete
。
如果您的指针将始终指向具有此类普通声明的对象,而不是使用new
创建的,则您必须自己确保仅在对象的生命周期内使用指针他们指着。在这种情况下,使用std::unique_ptr
并不会获得太多优势;您可以继续使用原始指针,当其他问题(此处为C ++语言本身)引起生命周期问题时,它仍然是表示指针的常用方式。
如果您希望指针的寿命超过创建对象的功能块,则不能使用普通的对象声明语法。一种可能的选择是要求所有对象创建都使用create
函数,而不是直接声明一个对象:
class Thing {
public:
static std::unique_ptr<Thing> create(const Thing& src)
{ return { new Thing(src) }; }
static std::unique_ptr<Thing> create(int data)
{ return { new Thing(data) }; }
void PrintData() const;
private:
// All constructors private, to make sure a Thing can ONLY be
// created by a create() function - including the copy constructor.
Thing(const Thing&) = default;
explicit Thing(int data) : data_(data) {}
int data_;
};
int main() {
auto thing_ptr = Thing::create(6);
thing_ptr->PrintData();
}