将unique_ptr对象移到vector对象中并继续使用

C++ Move a unique_ptr to a vector and continue using it

本文关键字:对象 继续 vector unique ptr      更新时间:2023-10-16

我开始玩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是无效的....如果是这样,解决方案是什么?

OBS:我无法使用指针移动到之后的向量。在实际应用中,这将在多线程环境中运行,其中一个磁头使用向量数据,而另一个继续使用原始指针p

唯一指针的名称说明了一切。这意味着它是完全唯一的,所以当它超出作用域时,它可以被安全地删除。

当你在指针上使用std::move时,它将其强制转换为右值引用,然后调用move构造函数,这意味着它被移动,而不是复制。这就像如果你把盘子从洗碗机里移到橱柜里,它并不在洗碗机里。在代码中,这意味着被移动的unique_ptr被设置为nullptr

选择:

  1. 使用refcount的shared_ptr。这将允许您拥有多个实例,并在删除最后一个实例后调用析构函数。使用这种方法的另一个好处是,如果vector不应该阻止对象被销毁,那么它可以存储weak_ptr s。
  2. unique_ptr上使用std::move之前缓存原始指针以将其移动到vector中。这可能是不安全的,因为如果您试图在vector销毁之后使用该指针,它将是未定义行为,因为它将是一个悬空引用。

简而言之,不,任何对象在移动后使用都是无效的。编辑:除非你正在调用一个没有先决条件的函数(谢谢,Benjamin Lindley)。

这是因为当你std::move a unique_ptr时,你将该内存的所有权转移给了另一个unique_ptr。(真正发生的是,std::moveunique_ptr标记为r值引用,然后另一个unique_ptr的构造函数看到这一点并高兴地执行指针窃取)。你移到的unique_ptr现在可以做任何它想做的事情,包括删除内存和使你拥有的任何其他引用无效。

您可以将指针解引用为原始指针(通过unique_ptr::get())以访问它所指向的内容,然后将唯一指针移动到vector中。然而,unique_ptr的整体理念是唯一所有权;您的原始指针随时可能失效。