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