我开始玩std::unique_ptr
并且我不想搞砸事情。
在我的代码中,我创建了一个std::unique_ptr
,将其存储在vector
中,以便以后在另一个上下文中使用,并继续使用指针:
#include <iostream>
#include <string>
#include <memory>
#include <vector>
class MyClass {
public:
void doWhatever ()
{
std::cout << "Var = " << variable << std::endl;
}
int variable = 0;
};
class Controller {
public:
std::vector<std::unique_ptr<MyClass>> instances;
};
class OtherClass {
public:
void myFunction()
{
Controller control;
std::unique_ptr<MyClass> p(new MyClass);
control.instances.push_back(std::move(p));
// Continue using p.
p->doWhatever(); // Is this valid ?
p->variable = 10; // Is this valid ?
p->doWhatever(); // Is this valid ?
}
};
int main()
{
OtherClass cl;
cl.myFunction();
}
代码编译,但我在执行时遇到分段错误。
我想在将指针移动到向量后调用p
是无效的......如果是这样,那么解决方案是什么?转到shared_ptr?
OBS:在使用指针后,我无法移动到。在实际应用程序中,这将在多线程环境中运行,其中一个使用矢量数据,另一个继续使用原始指针p
。
感谢您的帮助。
答案 0 :(得分:3)
唯一指针的名称说明了一切。它意味着完全独特,因此当它超出范围时,可以安全地删除它。
当你在指针上使用std::move
时,它会将它转换为右值参考帽,然后调用移动构造函数,这意味着它被移动,而不是被复制。就像你将一个盘子从洗碗机移到柜子里一样,它不在洗碗机里。在代码中,这意味着移出的unique_ptr
设置为nullptr
备选方案:
shared_ptr
。这将允许您拥有多个实例,在删除最后一个实例后,将调用析构函数。使用它的另一个好处是,如果它不应该保持对象不被破坏,那么向量可以存储weak_ptr
s。 std::move
上使用unique_ptr
之前缓存原始指针,将其移至vector
。这可能是不安全的,因为如果在向量被销毁后尝试使用该指针,则它是未定义的行为,因为它将是一个悬空引用。 答案 1 :(得分:1)
简而言之,在您移动它之后使用任何对象并不是无效的。编辑:除非你正在调用一个没有先决条件的函数(谢谢,本杰明林德利)。
这是因为当您std::move
unique_ptr
时,您正在将该内存的所有权转让给另一个unique_ptr
。 (真正发生的是std::move
将您的unique_ptr
标记为r值引用,然后另一个unique_ptr
的构造函数看到这个并且兴高采烈地执行指针窃取)。您已移入的unique_ptr
现在可以执行任何操作,包括删除内存并使您拥有的任何其他引用无效。
您可以将指针取消引用到原始指针(通过unique_ptr::get()
)以访问它指向的内容,然后将唯一指针移动到向量中。但是,unique_ptr
的整个想法是唯一所有权;你的原始指针随时都可能变得无效。