我有一个案例,我不确定是否应该使用 unique_ptr
或按值传递对象。
假设我有 A 类,它有一个 B 类 vector ,而 C 类也有一个 B 类 vector 。每次我将 B 对象添加到 C 类中的 vector 时,都应该将其从 C 类 vector 中删除,反之亦然。当对象 C 被销毁时,B Vector 类中的所有对象都应添加到 A 类中的 B Vector
class B {
public:
B();
virtual ~B();
};
class A {
C & c;
std::vector<B> bs;
public:
A(C & c ): c(c){};
virtual ~A();
void add(B b){
bs.push_back(b);
c.remove(b);
}
void remove(B b){
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());
}
};
class C {
public:
A & a;
std::vector<B> bs;
C(A & a): a(a) {
};
virtual ~C(){
for (B b : bs) {
a.add(b);
remove(b);
}
}
void add(B b){
bs.push_back(b);
a.remove(b);
}
void remove(B b){
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());
}
};
我的问题:
- 在这种情况下使用指针更好吗?我应该总是有一个唯一的 B 对象!换句话说,如果两个 b 对象的内容不同,它们仍然不同,因为内存中的地址不同。
- 我想在 C++ 11 中的 smart_pointers 的帮助下编写这段代码!
shared_ptr
和unique_ptr
哪种类型更好? B 对象永远不会被两个对象所拥有,并且它始终只有一个所有者,因此我猜unique_ptr
更好,但我不确定。 - 如何使用 unique_ptr 编写上面的代码?
最佳答案
如果复制构造
B
成本高昂,那么(智能)指针可能是个好主意(重新设计应用程序逻辑可能是另一种解决方案),如果我理解正确的话,给定的
B
实例始终由单个所有者(A
或C
)操纵。因此,std::unique_ptr
是一个合理的选择,尝试以下实现。我还没有编译它,但我想你会明白的:)
.
class B {
public:
B();
virtual ~B();
};
class A {
C & c;
std::vector<std::unique_ptr<B>> bs;
public:
A(C & c ): c(c){};
virtual ~A();
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (c) Passing unique_ptr by value means "sink."
void add(std::unique_ptr<B> b){
c.remove(b); // release the poiner from the other container
bs.emplace_back(b.get()); // emplace the pointer in the new one
b.release(); // emplacement successful. release the pointer
}
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (d) Passing unique_ptr by reference is for in/out unique_ptr parameters.
void remove(std::unique_ptr<B>& b){
// @todo check that ther returned pointer is != bs.end()
std::find(bs.begin(), bs.end(), b)->release(); // first release the pointer
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end()); // then destroy its owner
}
};
class C {
public:
A & a;
std::vector<std::unique_ptr<B>> bs;
C(A & a): a(a) {
};
virtual ~C(){
for (auto&& b : bs) {
a.add(b);
// a is going to call this->remove()...
// unless calling this->remove() from "a"
// while this is being destroyed is Undefined Behavior (tm)
// I'm not sure :)
}
}
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (c) Passing unique_ptr by value means "sink."
void add(std::unique_ptr<B> b){
c.remove(b); // release the poiner from the other container
bs.emplace_back(b.get()); // emplace the pointer in the new one
b.release(); // emplacement successful. release the pointer
}
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (d) Passing unique_ptr by reference is for in/out unique_ptr parameters.
void remove(std::unique_ptr<B>& b){
// @todo check that ther returned pointer is != bs.end()
std::find(bs.begin(), bs.end(), b)->release(); // first release the pointer
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end()); // then destroy its owner
}
};
关于c++ - 通过unique_ptr或通过值传递对象以及如何实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33187647/