在 unique_ptrs 向量中转移所有权
Transferring Ownership in vector of unique_ptrs
我有 2 classes 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 添加一个复制构造函数和一个赋值运算符
class B
{
public:
BVEC vec; //error is here
//....
B& operator=(B&b);
B(B&b);
};
但我仍然收到相同的错误消息。
那是因为 unique_ptr 是......唯一的,它们指向一个对象的整个点,当 unique_ptr 超出范围时 - 它删除它指向的变量。如果您可以轻松地将指向的变量分配给另一个unique_ptr,指向的变量什么时候会被删除?当第一个超出范围或第二个时?这里没有"uniqueness"
这就是为什么复制或赋值 unique_ptr 是不允许的,复制构造函数和赋值运算符被禁用
您正在寻找 shared_ptr。多个 shared_ptr 可以指向一个变量,当所有变量都超出范围时它会被删除,某种原始垃圾收集器
此代码在 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
中使用的删除器是什么。 (我已经在评论中提出了这个问题,但还没有看到回应。)我怀疑如果你为 B
编写了你的复制构造函数,为 A
编写了你的复制构造函数那么你的问题是正确的与您的删除器一起使用,AllocateA
.
您可以在我为 B
编写的复制构造函数中看到,我为 b.vec
中的每个 A
在 this.vec
中动态创建了相同的 A
].我认为这就是您想要的行为。如果你只想移动动态分配,我建议使用移动构造函数 as suggested by Michal Walenciak.
编辑:
在查看了 OP 的标题后,我觉得可能是一个移动构造函数。所以我也添加了其中之一。
我有 2 classes 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 添加一个复制构造函数和一个赋值运算符
class B
{
public:
BVEC vec; //error is here
//....
B& operator=(B&b);
B(B&b);
};
但我仍然收到相同的错误消息。
那是因为 unique_ptr 是......唯一的,它们指向一个对象的整个点,当 unique_ptr 超出范围时 - 它删除它指向的变量。如果您可以轻松地将指向的变量分配给另一个unique_ptr,指向的变量什么时候会被删除?当第一个超出范围或第二个时?这里没有"uniqueness"
这就是为什么复制或赋值 unique_ptr 是不允许的,复制构造函数和赋值运算符被禁用
您正在寻找 shared_ptr。多个 shared_ptr 可以指向一个变量,当所有变量都超出范围时它会被删除,某种原始垃圾收集器
此代码在 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
中使用的删除器是什么。 (我已经在评论中提出了这个问题,但还没有看到回应。)我怀疑如果你为 B
编写了你的复制构造函数,为 A
编写了你的复制构造函数那么你的问题是正确的与您的删除器一起使用,AllocateA
.
您可以在我为 B
编写的复制构造函数中看到,我为 b.vec
中的每个 A
在 this.vec
中动态创建了相同的 A
].我认为这就是您想要的行为。如果你只想移动动态分配,我建议使用移动构造函数 as suggested by Michal Walenciak.
编辑: 在查看了 OP 的标题后,我觉得可能是一个移动构造函数。所以我也添加了其中之一。