std :: unique_ptr尝试引用已删除的函数

时间:2015-11-21 21:52:46

标签: c++ c++11

我已经在Unity上工作了一段时间,然后回来使用Visual Studio 2015做一些C ++。我遇到了这个类定义

class A
{
public:
  A();
  virtual ~A();
  A(const A&) = delete;
  A& operator=(const A&) = delete;

private:
  …
}

此类动态分配如下:

ObjPtr obj = ObjPtr(new A());

其中ObjPtr是定义的类型,如下所示:

typedef std::unique_ptr<A> objPtr;

使用std::vector<ObjPtr>将这些创建的对象添加到std::move。有一次,我需要遍历对象列表,如果我找到满足我标准的东西,请保留一份副本。

ObjPtr keep;

for(auto& object : GetObjectList() )
{
  if(/*check if its the object I want*/)
  {
    keep = object;
  }
}

GetObjectList返回const std::vector<ObjPtr>&

但我得到了“试图引用已删除的功能”。我做了一些谷歌搜索并尝试删除= delete部分,甚至评论了2行。我甚至试图做

ObjPtr keep = std::move(object);

但我仍然收到删除的功能错误。任何人都可以看到我做错了什么或者指出了一些可以提供帮助的资源吗?

2 个答案:

答案 0 :(得分:9)

无法复制std::unique_ptr。即使托管对象可以(但你的不能)。

你在这里有几个选择(都有不同的效果):

  • keep的类型更改为非拥有原始指针(又名A *)并使用keep = object.get();。这是安全的,当且仅当您知道不会使用keep超过ObjectList(或更确切地说,您采用地址的对象)时,{/ p>

  • std::unique_ptr移出容器,即使用keep = std::move(object);。当然,现在你有ObjectList的差距。 (我知道你已经编辑了你的问题,说ObjectListconst,这意味着你不能修改它,因此不能将对象移出它。)

  • 如果您想要共享所有权语义,请将ObjPtr的类型更改为std::shared_ptr<A>

  • 如果您绝对需要对象的副本,则可以向virtual添加A成员函数,以多态方式克隆对象。

    class A
    {
    public:
      virtual std::unique_ptr<A> clone() = 0;
      …
    };
    

    然后,您在从class派生的每个叶子A中实现该功能。在循环中,然后使用keep = object->clone();。为此,您可能希望制作复制构造函数protected,但不要delete

    不要使用keep = std::make_unique<A>(*object);,因为它不会尊重对象的实际(动态)类型,并始终切换到A。 (由于您的A不可复制,因此无论如何都无法使用。)

答案 1 :(得分:1)

什么使得一个独特的指针&#34;独特&#34;是只有一个这样的指针指向一个对象。如果您制作了一个唯一指针的副本,那么您将拥有两个拥有基础对象的东西。当每一个被摧毁时,该对象将被销毁,导致双重删除。

如果您需要多个所有权,请使用shared_ptr。如果您不需要保留副本的代码的所有权,请不要保留副本,而是保留指针或引用。