【问题标题】:Transferring Ownership in vector of unique_ptrs在 unique_ptrs 向量中转移所有权
【发布时间】:2015-01-29 12:22:53
【问题描述】:

我有 2 个 A 和 B 类

//A.h
class A{};

// B.h
typedef unique_ptr<A, AllocateA> APtr;
typedef vector<APtr> BVEC;

class B
{
public:
   BVEC vec; //error is here
   //....
};

当我编译代码时,我得到unique_ptr....attempting to reference a deleted function

然后我像这样向 B 类添加一个复制构造函数和一个赋值运算符

class B
{
public:
   BVEC vec; //error is here
   //....
   B& operator=(B&b);
   B(B&b);
};

但我仍然收到相同的错误消息。

【问题讨论】:

  • unique_ptr 无法复制。试试 shared_ptr。
  • @user0175554 什么是AllocateA?请告诉我,这不是您命名删除器的名称。
  • 如果你想转让所有权,你不能有一个拷贝构造函数。复制操作应保持原件不变。
  • 为什么你的问题标题提到共享指针? unique_ptrshared_ptr 不一样
  • 您的复制构造函数和赋值运算符应采用const B&amp; 参数。

标签: c++ vector copy-constructor unique-ptr ownership


【解决方案1】:

那是因为 unique_ptr 是......唯一的,它们指向一个对象的整个点,当 unique_ptr 超出范围时 - 它会删除它指向的变量。如果您可以轻松地将指向的变量分配给另一个 unique_ptr,那么指向的变量何时会被删除?当第一个超出范围或第二个超出范围时?这里没有“独特性”。

这就是为什么不允许复制或分配 unique_ptr 的原因,复制 ctor 和赋值运算符被禁用

您正在寻找 shared_ptr 。多个 shared_ptr 可以指向一个变量,当它们全部超出范围时,它会被删除,某种原始垃圾收集器

【讨论】:

  • @MichałWalenciak 这与他的标题“转让所有权”一致,但与复制构造函数一致。
  • 谢谢您,先生,@user3613500 一如既往的好解释
【解决方案2】:

此代码在 gcc 4.9.2 和 Visual Studio 2013 上运行良好:

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

using namespace std;

//A.h
class A{
public:
    int alpha;
    A(int input) : alpha(input){}
};

// B.h
typedef unique_ptr<A> APtr;
typedef vector<APtr> BVEC;

class B
{
public:
    BVEC vec;
    B(){}
    const B& operator=(const B& b){
        vec.clear();
        for_each(b.vec.cbegin(), b.vec.cend(), [&](const unique_ptr<A>& i){vec.push_back(unique_ptr<A>(new A(*i))); });
        return b;
    }
    B(const B& b){
        vec.clear();
        for_each(b.vec.cbegin(), b.vec.cend(), [&](const unique_ptr<A>& i){vec.push_back(unique_ptr<A>(new A(*i))); });
    }
    const B& operator=(B&& b){
        vec.resize(b.vec.size());
        move(b.vec.begin(), b.vec.end(), vec.begin());
        return *this;
    }
    B(B&& b){
        vec.resize(b.vec.size());
        move(b.vec.begin(), b.vec.end(), vec.begin());
    }
};

int main() {
    B foo;
    B bar;

    for (auto i = 0; i < 10; ++i){
        foo.vec.push_back(unique_ptr<A>(new A(i)));
    }
    bar = foo;
    foo.vec.clear();

    for (auto& i : bar.vec){
        cout << i->alpha << endl;
    }
    foo = move(bar);

    for (auto& i : foo.vec){
        cout << i->alpha << endl;
    }
    return 0;
}

我不知道您在APtr 中使用的删除器是什么。 (我已经在 cmets 中提出了这个问题,但还没有看到回复。)我怀疑如果您正确编写了 B 的复制构造函数和 A 的复制构造函数,那么您的问题出在删除器上, AllocateA.

您可以在我为B 编写的复制构造函数中看到,我在this.vec 中为b.vec 中的每个A 动态创建一个相同的A。我认为这就是你想要的行为。如果您只想移动动态分配,我建议使用移动构造函数as suggested by Michal Walenciak

编辑: 在查看了 OP 的标题后,我觉得可能是一个移动构造函数。所以我也添加了其中之一。

【讨论】:

  • 谢谢,没有 AllocateA,我的程序将无法运行。我使用 shared_ptr 加上你的代码,但我也同意你的答案是正确的,除了我自己的情况。
猜你喜欢
  • 2013-01-20
  • 2011-08-13
  • 1970-01-01
  • 2010-11-30
  • 2015-10-07
  • 1970-01-01
  • 2014-10-10
  • 2017-08-04
  • 1970-01-01
相关资源
最近更新 更多