C ++将unique_ptr移动到向量并继续使用它

时间:2015-07-14 18:46:28

标签: c++ pointers c++11 vector unique-ptr

我开始玩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

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

唯一指针的名称说明了一切。它意味着完全独特,因此当它超出范围时,可以安全地删除它。

当你在指针上使用std::move时,它会将它转换为右值参考帽,然后调用移动构造函数,这意味着它被移动,而不是被复制。就像你将一个盘子从洗碗机移到柜子里一样,它不在洗碗机里。在代码中,这意味着移出的unique_ptr设置为nullptr

备选方案:

  1. 使用引用计数shared_ptr。这将允许您拥有多个实例,在删除最后一个实例后,将调用析构函数。使用它的另一个好处是,如果它不应该保持对象不被破坏,那么向量可以存储weak_ptr s。
  2. 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的整个想法是唯一所有权;你的原始指针随时都可能变得无效。