[英]Passing object by unique_ptr or by value and how to implement
我有一種情況,我不確定是否應該使用unique_ptr
或按值傳遞Object。
假設我有A類,其向量為B類,而C類也有向量,為B類。 每次我在C類的Vector中添加B對象時,都應將其從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());
}
};
我的問題:
shared_ptr
或unique_ptr
更好? AB對象永遠不會由兩個對象擁有,並且它始終只有一個所有者,因此我猜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
}
};
如果需要的話,我只會使用unique_ptr
。 您可能希望將B
設置為僅移動類型(例如unique_ptr
)以限制所有權。
如果B
移動成本很高,或者防止B
的復制不切實際,請使用unique_ptr
但要注意,您隨后要為動態內存分配付費。
在受代碼啟發的示例中,這是如何使用僅移動B
的方法。 如果您使用unique_ptr
則它應該完全相同:
struct B {
B();
B(B&&) = default; // Explicitly default the
B& operator=(B&&) = default; // move functions.
B(const B&) = delete; // Delete copy functions - Not strictly
B& operator=(const B&) = delete; // necessary but just to be explicit.
};
struct A {
std::vector<B> bs;
void add(B b){
bs.push_back(std::move(b));
}
B remove(std::vector<B>::iterator itr){
B tmp = std::move(*itr);
bs.erase(itr);
return tmp;
}
};
struct C {
A& a;
std::vector<B> bs;
C(A& a) : a(a) {}
~C(){
for (auto& b : bs) {
a.add(std::move(b));
}
} // bs will be deleted now anyway, no need to remove the dead objects
void add(B b){
bs.push_back(std::move(b));
}
B remove(std::vector<B>::iterator itr){
auto tmp = std::move(*itr);
bs.erase(itr);
return tmp;
}
};
int main() {
A a;
C c(a);
a.add(B());
auto tmp = a.remove(a.bs.begin());
c.add(std::move(tmp));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.