如何将 unique_ptr 从向量 <unique_ptr<Foo>> 中移出?
How do you move a unique_ptr out of an vector<unique_ptr<Foo>>?
我想从 vector<unique_ptr<Foo>>
中移出 unique_ptr<Foo>
。考虑我的代码:
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
class Foo {
public:
int x;
Foo(int x): x(x) {};
~Foo() {
cout << "Destroy of id: " << x << "\n";
x = -1;
};
};
int main(int argc, char *argv[]) {
auto foos = vector<unique_ptr<Foo>>();
foos.push_back(unique_ptr<Foo>(new Foo(100)));
foos.push_back(unique_ptr<Foo>(new Foo(101)));
foos.push_back(unique_ptr<Foo>(new Foo(102)));
// Print all
cout << "Vector size: " << foos.size() << "\n";
for (auto i = foos.begin(); i != foos.end(); ++i) {
cout << (*i)->x << "\n";
}
// Move Foo(100) out of the vector
{
auto local = move(foos.at(0));
cout << "Removed element: " << local->x << "\n";
}
// Print all! Fine right?
cout << "Vector size: " << foos.size() << "\n";
for (auto i = foos.begin(); i != foos.end(); ++i) {
cout << (*i)->x << "\n";
}
return 0;
}
我预计它会产生:
Vector size: 3
100
101
102
Removed element: 100
Destroy of id: 100
Vector size: 2
101
102
但是,我得到了这个结果:
Vector size: 3
100
101
102
Removed element: 100
Destroy of id: 100
Vector size: 3
Segmentation fault: 11
为什么我的向量大小仍然是 3,为什么我会遇到分段错误?我怎样才能得到我想要的结果?
让我们将您的问题简化为:
vector<unique_ptr<Foo>> foos;
foos.push_back(unique_ptr<Foo>(new Foo(100)));
auto local = std::move(foos[0]);
std::cout << foos[0]->x << '\n';
通过移动 foos[0]
创建 local
后,foos[0]
不再拥有指针的所有权。它是空的。取消引用它成为未定义的行为,在您的情况下表现为分段错误。此时的vector
是完美的"intact",它包含一个空的unique_ptr
,等价于状态:
vector<unique_ptr<Foo>> foos(1);
您应该简单地检查您的unique_ptr
在取消引用之前拥有一个指针:
if (foos[0]) {
// we wouldn't get here
std::cout << foos[0]->x << '\n';
}
或者,由于您想强制执行 vector
仅包含有效指针的不变性,作为移出操作的一部分,您应该 erase
该元素:
auto local = std::move(foos[0]);
foos.erase(foos.begin());
// now foos is empty
我想从 vector<unique_ptr<Foo>>
中移出 unique_ptr<Foo>
。考虑我的代码:
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
class Foo {
public:
int x;
Foo(int x): x(x) {};
~Foo() {
cout << "Destroy of id: " << x << "\n";
x = -1;
};
};
int main(int argc, char *argv[]) {
auto foos = vector<unique_ptr<Foo>>();
foos.push_back(unique_ptr<Foo>(new Foo(100)));
foos.push_back(unique_ptr<Foo>(new Foo(101)));
foos.push_back(unique_ptr<Foo>(new Foo(102)));
// Print all
cout << "Vector size: " << foos.size() << "\n";
for (auto i = foos.begin(); i != foos.end(); ++i) {
cout << (*i)->x << "\n";
}
// Move Foo(100) out of the vector
{
auto local = move(foos.at(0));
cout << "Removed element: " << local->x << "\n";
}
// Print all! Fine right?
cout << "Vector size: " << foos.size() << "\n";
for (auto i = foos.begin(); i != foos.end(); ++i) {
cout << (*i)->x << "\n";
}
return 0;
}
我预计它会产生:
Vector size: 3
100
101
102
Removed element: 100
Destroy of id: 100
Vector size: 2
101
102
但是,我得到了这个结果:
Vector size: 3
100
101
102
Removed element: 100
Destroy of id: 100
Vector size: 3
Segmentation fault: 11
为什么我的向量大小仍然是 3,为什么我会遇到分段错误?我怎样才能得到我想要的结果?
让我们将您的问题简化为:
vector<unique_ptr<Foo>> foos;
foos.push_back(unique_ptr<Foo>(new Foo(100)));
auto local = std::move(foos[0]);
std::cout << foos[0]->x << '\n';
通过移动 foos[0]
创建 local
后,foos[0]
不再拥有指针的所有权。它是空的。取消引用它成为未定义的行为,在您的情况下表现为分段错误。此时的vector
是完美的"intact",它包含一个空的unique_ptr
,等价于状态:
vector<unique_ptr<Foo>> foos(1);
您应该简单地检查您的unique_ptr
在取消引用之前拥有一个指针:
if (foos[0]) {
// we wouldn't get here
std::cout << foos[0]->x << '\n';
}
或者,由于您想强制执行 vector
仅包含有效指针的不变性,作为移出操作的一部分,您应该 erase
该元素:
auto local = std::move(foos[0]);
foos.erase(foos.begin());
// now foos is empty