简体   繁体   English

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

[英]C++ Move a unique_ptr to a vector and continue using it

I´m starting playing around with std::unique_ptr and I just don´t want to mess up things. 我开始玩std::unique_ptr而我只是不想弄乱东西。

On my code, I´m creating a std::unique_ptr , storing it on a vector for later use in another context and continue using the pointer: 在我的代码上,我正在创建一个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();
    }

The code compiles, but I´m getting segmentation fault on execution. 代码可以编译,但是执行时出现分段错误。

I imagine that calls to p after moving the pointer to the vector are invalid.... If so, what would be the solution here ? 我认为将指针移到向量后对p调用无效。...如果是这样,这里的解决方案是什么? Moving to a shared_ptr ? 移到shared_ptr吗?

OBS: I cannot move to vector after using the pointer. OBS:使用指针后,我无法移至矢量。 In real application this will be running on a multi-threaded environment where one thead is using the vector data and the other continue using the original pointer p . 在实际应用中,这将在多线程环境中运行,其中一个主题正在使用矢量数据,而另一个主题则继续使用原始指针p

Thanks for helping. 感谢您的帮助。

The name of unique pointer says it all. 唯一指针的名称说明了一切。 It is meant to be completely unique so when it goes out of scope it can be safely deleted. 它的意思是完全唯一,因此当超出范围时可以安全删除。

When you use std::move on the pointer, it casts it to a rvalue reference hat then invokes the move constructor, meaning it is moved, not copied. 当您在指针上使用std::move时,它将其强制转换为右值引用帽子,然后调用move构造函数,这意味着它已被移动而不是被复制。 It is just like if you move a plate from the dishwasher to the cabinet, it isn't in the dishwasher. 就像您将盘子从洗碗机移到机柜一样,它不在洗碗机中。 In code, that means that the unique_ptr that is moved from is set to nullptr 在代码中,这意味着将从其移动的unique_ptr设置为nullptr

Alternatives: 备择方案:

  1. Use a ref counted shared_ptr . 使用引用计数shared_ptr This will allow you to have multiple instances and after the last one is deleted the destructor will be called. 这将允许您有多个实例,删除最后一个实例后,将调用析构函数。 Another plus of using this is that the vector could store weak_ptr s if it shouldn't keep the object from being destroyed. 使用此方法的另一个weak_ptr是,如果向量不应该防止对象被破坏,则可以存储weak_ptr
  2. Cache the raw pointer before using std::move on the unique_ptr to move it into the vector . unique_ptr上使用std::move将其移动到vector之前,请缓存原始指针。 This potentially unsafe because if you try to use that pointer after the vector is destroyed it is undefined behaviors because it would be a dangling reference. 这可能是不安全的,因为如果在向量被销毁后尝试使用该指针,则它是未定义的行为,因为它将是一个悬挂的引用。

In brief, no it is not valid to use any object after you've moved it. 简而言之,不可以,在移动任何对象后,它都是无效的。 EDIT: Unless you are calling a function that has no preconditions (Thanks, Benjamin Lindley). 编辑:除非您正在调用没有先决条件的函数(谢谢,本杰明·林德利)。

This is because when you std::move a unique_ptr , you are transferring ownership of that memory to another unique_ptr . 这是因为当您std::move unique_ptr ,您正在将该内存的所有权转移到另一个unique_ptr (What's really happening is that std::move marks your unique_ptr as an r-value reference, and then the constructor for the other unique_ptr sees this and gleefully performs pointer stealing). (真正发生的事情是std::move您的unique_ptr标记为r值引用,然后另一个unique_ptr的构造函数看到了这一点并高兴地执行了指针窃取)。 The unique_ptr that you've moved into can now do whatever it wants, including delete the memory and invalidate any other reference you have. 现在,您已进入的unique_ptr可以执行所需的任何操作,包括删除内存并使任何其他引用无效。

You can dereference the pointer into a raw pointer (via unique_ptr::get() ) to access what it's pointing at, and then move the unique pointer into the vector. 您可以将指针解引用为原始指针(通过unique_ptr::get() )以访问其指向的对象,然后将唯一指针移至向量中。 However, the whole idea of a unique_ptr is sole ownership; 但是, unique_ptr的整个想法是唯一所有权。 your raw pointer could at any time become invalid. 您的原始指针可能随时变为无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM