封装对象和管理其生命周期的最佳方法是什么?示例:我有一个类A,它包含一个B类型的对象,并且完全负责它.
解决方案1,克隆b对象以确保只有A能够清理它.
class A { B *b; public: A(B &b) { this->b = b.clone(); } ~A() { delete b; // safe } };
解决方案2,直接使用传递的对象,我们冒险潜在的双重免费在这里.
class A { B *b; public: A(B *b) { this->b = b; } ~A() { delete b; // unsafe } };
在我的实际案例中,解决方案#2最适合.但是我想知道这是否被认为是错误的代码,因为有人可能不知道A的行为,即使它已被记录.我可以想到这些场景:
B *myB = new B(); A *myA = new A(myB); delete myB; // myA contains a wild pointer now
要么,
B *myB = new B(); A *firstA = new A(myB); A *secondA = new A(myB); // bug! double assignment delete firstA; // deletes myB, secondA contains a wild pointer now delete secondA; // deletes myB again, double free
如果我正确记录A的行为,我可以忽略这些问题吗?是否足以宣布责任并让其他人阅读文档?如何在您的代码库中管理?
我从不删除任何东西,除非我真的必须这样做.这会导致错误.
聪明的指针是你的朋友. std::auto_ptr<>
当一个对象拥有另一个对象并且在超出范围时负责删除它是你的朋友. boost::shared_ptr<>
(或者,现在,std::tr1::shared_ptr<>
)是你的朋友,当有多个对象附加到另一个对象时,你希望在没有更多引用的情况下删除该对象.
因此,要么使用您的解决方案1,要么使用您的解决auto_ptr
方案2 shared_ptr
.