智能指针(boost)解释
以下一组指针有什么区别? 什么时候在生产代码中使用每个指针?
例如,将不胜感激!
-
scoped_ptr
-
shared_ptr
-
weak_ptr
-
intrusive_ptr
你在生产代码中使用boost吗?
智能指针的基本属性
具有可以分配每个智能指针的属性很容易。 有三个重要的属性。
- 根本没有所有权
- 所有权转移
- 所有权份额
第一种意思是智能指针不能删除对象,因为它不拥有它。 第二种意思是只有一个智能指针可以同时指向同一个对象。 如果智能指针要从函数返回,则所有权被转移到返回的智能指针。
第三种意思是多个智能指针可以同时指向同一个对象。 这也适用于一个原始指针 ,但是原始指针缺less一个重要的特征:它们没有定义它们是否拥有 。 如果每个所有者放弃对象,则所有权智能指针将会删除该对象。 这种行为恰巧经常需要,所以共享拥有智能指针被广泛传播。
一些拥有智能指针既不支持第二,也不支持第三。 因此,他们不能从function中退回或者在别的地方通过。 哪一个最适合于RAII
目的,智能指针保持本地化,只是创build它,使它在超出范围之后释放一个对象。
所有权的分享可以通过具有拷贝构造函数来实现。 这自然会复制一个智能指针,复制和原始都将引用同一个对象。 所有权的转移目前无法在C ++中实现,因为没有办法将某个对象从某个对象转移到另一个对象所支持的语言:如果您尝试从某个函数返回一个对象,那么发生的事情就是该对象被复制了。 所以实现所有权转移的智能指针必须使用拷贝构造函数来实现所有权的转移。 然而,这反过来又打破了它在容器中的使用,因为需求陈述了容器元素的复制构造函数的某些行为,这些行为与这些智能指针的这种所谓的“移动构造函数”行为不兼容。
C ++ 1x通过引入所谓的“移动构造函数”和“移动赋值操作符”,提供了对所有权转移的本地支持。 它还带有一个名为unique_ptr
这种所有权转移智能指针。
分类智能指针
scoped_ptr
是一个既不可转让又不可共享的智能指针。 如果你在本地需要分配内存的话,它是可用的,但是当它超出范围时,确保它被再次释放。 但是如果你愿意,它仍然可以和另一个scoped_ptr交换。
shared_ptr
是共享所有权的智能指针(上面的第三种)。 它是引用计数,所以它可以看到它的最后一个副本何时超出范围,然后释放被pipe理的对象。
weak_ptr
是一个非拥有的智能指针。 它被用来引用一个被pipe理的对象(由一个shared_ptrpipe理)而不增加一个引用计数。 通常情况下,您需要将原始指针从shared_ptr中取出并复制。 但这不是安全的,因为你无法检查对象何时被删除。 所以,weak_ptr通过引用由shared_ptrpipe理的对象来提供方法。 如果需要访问对象,可以locking对象的pipe理(以避免在另一个线程中,shared_ptr在使用该对象时将其释放),然后使用它。 如果weak_ptr指向一个已经被删除的对象,它会通过抛出一个exception来注意到你。 当你有一个循环引用时,使用weak_ptr是最有利的:引用计数不能轻易应付这种情况。
intrusive_ptr
就像是一个shared_ptr,但是它不会将引用计数保存在shared_ptr中,而是将计数递增/递减到一些辅助函数,这些辅助函数需要由被pipe理的对象来定义。 这样做的好处是可以将一个已经被引用的对象(引用计数增加了一个外部引用计数机制)填充到intrusive_ptr中 – 因为引用计数不再是智能指针的内部,而是智能指针使用现有的参考计数机制。
unique_ptr
是所有权指针的转移。 你不能复制它,但你可以通过使用C ++ 1x的移动构造函数来移动它:
unique_ptr<type> p(new type); unique_ptr<type> q(p); // not legal! unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
这是std :: auto_ptr服从的语义,但是由于缺less对移动的本地支持,所以无法为它们提供无缺陷。 unique_ptr会自动从临时的其他unique_ptr中窃取资源,这是移动语义的关键特征之一。 auto_ptr将在下一个C ++ Standard版本中被弃用,以支持unique_ptr。 C ++ 1x也允许填充只能移动但不可复制到容器中的对象。 所以你可以把unique_ptr的东西插入到一个向量中。 如果你想了解更多关于这方面的信息,我会在这里停下来,并且引用你一篇有关这篇文章的文章 。
scoped_ptr是最简单的。 当它超出范围,它被破坏。 以下代码是非法的(scoped_ptrs是不可复制的),但会说明一点:
std::vector< scoped_ptr<T> > tPtrVec; { scoped_ptr<T> tPtr(new T()); tPtrVec.push_back(tPtr); // raw T* is freed } tPtrVec[0]->DoSomething(); // accessing freed memory
shared_ptr是引用计数。 每次发生复制或分配时,引用计数都会递增。 每当一个实例的析构函数被触发时,原始T *的引用计数递减。 一旦它为0,指针就被释放。
std::vector< shared_ptr<T> > tPtrVec; { shared_ptr<T> tPtr(new T()); // This copy to tPtrVec.push_back and ultimately to the vector storage // causes the reference count to go from 1->2 tPtrVec.push_back(tPtr); // num references to T goes from 2->1 on the destruction of tPtr } tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe
weak_ptr是对共享指针的弱引用,需要您检查指向的shared_ptr是否仍在
std::vector< weak_ptr<T> > tPtrVec; { shared_ptr<T> tPtr(new T()); tPtrVec.push_back(tPtr); // num references to T goes from 1->0 } shared_ptr<T> tPtrAccessed = tPtrVec[0].lock(); if (tPtrAccessed[0].get() == 0) { cout << "Raw T* was freed, can't access it" } else { tPtrVec[0]->DoSomething(); // raw }
intrusive_ptr通常用于需要使用第三方智能ptr的情况。 它会调用一个免费的函数来增加和减less引用计数。参见链接来提高文档的更多信息。
在boost智能指针的调查中,不要忽视boost::ptr_container
。 在例如std::vector<boost::shared_ptr<T> >
情况下,它们可能是非常有用的。
我第二个关于看文档的build议。 它不像看起来那么可怕。 还有一些简短的提示:
-
scoped_ptr
– 指针超出范围时自动删除的指针。 注 – 不可能分配任务,但不会引入开销 -
intrusive_ptr
– 不带smart_ptr
开销的引用计数指针。 但是对象本身存储引用计数 -
weak_ptr
– 与shared_ptr
一起处理导致循环依赖的情况(阅读文档,并在google上search漂亮的图片;) -
shared_ptr
– 通用的,function最强大的(也是重量级的)智能指针(来自boost提供的指针) - 还有一个旧的
auto_ptr
,它确保当控件离开一个范围时,它指向的对象被自动销毁。 然而它有不同的复制语义比其他人。 -
unique_ptr
– 将带有C ++ 0x
回复编辑:是的