使用时,你有什么方法可以用脚射击自己boost::shared_ptr
?换句话说,当我使用时,我必须避免哪些陷阱boost::shared_ptr
?
循环引用:shared_ptr<>
对于具有shared_ptr<>
原始对象的内容.weak_ptr<>
当然,你可以用来打破这个循环.
我在评论中添加以下内容作为我所谈论的内容的一个例子.
class node : public enable_shared_from_this{ public : void set_parent(shared_ptr parent) { parent_ = parent; } void add_child(shared_ptr child) { children_.push_back(child); child->set_parent(shared_from_this()); } void frob() { do_frob(); if (parent_) parent_->frob(); } private : void do_frob(); shared_ptr parent_; vector< shared_ptr > children_; };
在此示例中,您有一个节点树,每个节点都包含指向其父节点的指针.无论出于何种原因,frob()成员函数都会向上穿过树.(这不完全是古怪的;一些GUI框架以这种方式工作).
问题是,如果您失去对最顶层节点的引用,那么最顶层的节点仍然拥有对其子节点的强引用,并且其所有子节点也对其父节点具有强引用.这意味着存在循环引用,使所有实例不能自行清理,而实际上无法从代码中到达树,这个内存泄漏.
class node : public enable_shared_from_this{ public : void set_parent(shared_ptr parent) { parent_ = parent; } void add_child(shared_ptr child) { children_.push_back(child); child->set_parent(shared_from_this()); } void frob() { do_frob(); shared_ptr parent = parent_.lock(); // Note: parent_.lock() if (parent) parent->frob(); } private : void do_frob(); weak_ptr parent_; // Note: now a weak_ptr<> vector< shared_ptr > children_; };
这里,父节点已被弱指针替换.它在它所引用的节点的生命周期中不再有发言权.因此,如果最顶层的节点超出了前一个示例中的范围,那么虽然它拥有对其子节点的强引用,但它的子节点并不强烈引用其父节点.因此,对该对象没有强烈的引用,它会清理自己.反过来,这会导致孩子失去一个强大的参考,导致他们清理,等等.简而言之,这不会泄漏.并且通过战略性地用weak_ptr <>替换shared_ptr <>.
注意:上面同样适用于std :: shared_ptr <>和std :: weak_ptr <>,就像它对boost :: shared_ptr <>和boost :: weak_ptr <>一样.
shared_ptr
为同一个对象创建多个不相关的:
#include#include "boost/shared_ptr.hpp" class foo { public: foo() { printf( "foo()\n"); } ~foo() { printf( "~foo()\n"); } }; typedef boost::shared_ptr pFoo_t; void doSomething( pFoo_t p) { printf( "doing something...\n"); } void doSomethingElse( pFoo_t p) { printf( "doing something else...\n"); } int main() { foo* pFoo = new foo; doSomething( pFoo_t( pFoo)); doSomethingElse( pFoo_t( pFoo)); return 0; }
构造一个匿名临时共享指针,例如在函数调用的参数内:
f(shared_ptr(new Foo()), g());
这是因为允许new Foo()
执行,然后g()
调用,并g()
抛出异常,而无需shared_ptr
设置,因此shared_ptr
没有机会清理Foo
对象.
小心地将两个指针指向同一个对象.
boost::shared_ptrb( new Derived() ); { boost::shared_ptr d( b.get() ); } // d goes out of scope here, deletes pointer b->doSomething(); // crashes
而是使用这个
boost::shared_ptrb( new Derived() ); { boost::shared_ptr d = boost::dynamic_pointer_cast ( b ); } // d goes out of scope here, refcount-- b->doSomething(); // no crash
此外,任何持有shared_ptrs的类都应该定义复制构造函数和赋值运算符.
不要尝试在构造函数中使用shared_from_this() - 它将不起作用.而是创建一个静态方法来创建类并让它返回一个shared_ptr.
我已经毫无困难地传递了对shared_ptrs的引用.只需确保在保存之前复制它(即没有作为类成员的引用).
这有两件事要避免:
调用get()
函数获取原始指针并在指向对象超出范围后使用它.
将引用或原始指针传递给a也shared_ptr
应该是危险的,因为它不会增加内部计数,这有助于保持对象存活.
我们调试了几周奇怪的行为.
原因是:
我们将'this'传递给了一些线程工作者而不是'shared_from_this'.