以下指针集之间有什么区别?什么时候在生产代码中使用每个指针,如果有的话?
例子将不胜感激!
scoped_ptr
shared_ptr
weak_ptr
intrusive_ptr
你在生产代码中使用boost吗?
当您拥有可以分配每个智能指针的属性时,这很容易.有三个重要的属性.
根本没有所有权
所有权转让
所有权份额
第一个意味着智能指针不能删除对象,因为它不拥有它.第二个意味着只有一个智能指针可以同时指向同一个对象.如果要从函数返回智能指针,则所有权将转移到返回的智能指针.
第三个意味着多个智能指针可以同时指向同一个对象.这也适用于原始指针,但原始指针缺少一个重要特征:它们不定义它们是否拥有.如果每个所有者放弃该对象,则共享所有权智能指针将删除该对象.这种行为恰好需要经常使用,因此共享拥有的智能指针广泛传播.
一些拥有智能指针既不支持第二个也不支持第三个.因此,它们不能从函数返回或传递到其他地方.哪个最适合RAII
智能指针保持在本地并且刚刚创建的目的,以便在超出范围后释放对象.
可以通过拥有复制构造函数来实现所有权共享.这自然会复制一个智能指针,副本和原始文件都将引用同一个对象.所有权的转移当前并不能真正用C++实现,因为没有办法将某些东西从一个对象转移到另一个对象支持的语言:如果你试图从一个函数返回一个对象,那么正在发生的事情是该对象被复制.因此,实现所有权转移的智能指针必须使用复制构造函数来实现所有权的转移.然而,这反过来又破坏了它在容器中的使用,因为需求声明了容器元素的复制构造函数的某种行为,这与这些智能指针的所谓"移动构造函数"行为不相容.
C++ 1x通过引入所谓的"移动构造函数"和"移动赋值运算符"为所有权转移提供本机支持.它还附带了一个名为的所有权转移智能指针unique_ptr
.
scoped_ptr
是一个既不可转移也不可共享的智能指针.它只是在本地需要分配内存时才可用,但是当它超出范围时确保它再次被释放.但如果您愿意,它仍然可以与另一个scoped_ptr交换.
shared_ptr
是一个共享所有权的智能指针(上面第三种).它是引用计数,因此它可以看到它的最后一个副本超出范围,然后释放所管理的对象.
weak_ptr
是一个非拥有的智能指针.它用于引用托管对象(由shared_ptr管理),而不添加引用计数.通常,您需要从shared_ptr中获取原始指针并复制它.但这不安全,因为你无法检查对象何时被实际删除.因此,weak_ptr通过引用shared_ptr管理的对象来提供方法.如果您需要访问该对象,您可以锁定它的管理(以避免在另一个线程中,shared_ptr在您使用该对象时释放它)然后使用它.如果weak_ptr指向已删除的对象,它将通过抛出异常来通知您.当你有一个循环引用时,使用weak_ptr是最有益的:引用计数不能轻易应对这种情况.
intrusive_ptr
就像shared_ptr一样,但它不会将引用计数保留在shared_ptr中,而是将计数递增/递减到需要由托管对象定义的某些辅助函数.这样做的好处是,已经引用的对象(具有由外部引用计数机制递增的引用计数)可以填充到intrusive_ptr中 - 因为引用计数不再是智能指针内部的,但智能指针使用现有的参考计数机制.
unique_ptr
是所有权指针的转移.你无法复制它,但你可以使用C++ 1x的移动构造函数来移动它:
unique_ptrp(new type); unique_ptr q(p); // not legal! unique_ptr r(move(p)); // legal. p is now empty, but r owns the object unique_ptr s(function_returning_a_unique_ptr()); // legal!
这是std :: auto_ptr遵循的语义,但由于缺少对移动的本机支持,它无法提供它们而没有陷阱.unique_ptr将自动从临时的其他unique_ptr中窃取资源,这是移动语义的关键特性之一.auto_ptr将在下一个C++标准版本中弃用,而不是unique_ptr.C++ 1x还允许填充仅可移动但不可复制到容器中的对象.因此,您可以将unique_ptr填充到矢量中.如果你想了解更多相关信息,我会在这里停下来并引用你一篇关于此的精彩文章.
scoped_ptr是最简单的.当它超出范围时,它就会被销毁.以下代码是非法的(scoped_ptrs是不可复制的),但将说明一点:
std::vector< scoped_ptr> tPtrVec; { scoped_ptr 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> tPtrVec; { shared_ptr 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> tPtrVec; { shared_ptr tPtr(new T()); tPtrVec.push_back(tPtr); // num references to T goes from 1->0 } shared_ptr tPtrAccessed = tPtrVec[0].lock(); if (tPtrAccessed[0].get() == 0) { cout << "Raw T* was freed, can't access it" } else { tPtrVec[0]->DoSomething(); // raw }
当您必须使用第三方智能ptr时,通常会使用intrusive_ptr.它将调用一个自由函数来添加和减少引用计数.请参阅提升文档的链接以获取更多信息.
不要忽视boost::ptr_container
任何有关boost智能指针的调查.在例如std::vector
太慢的情况下,它们可能是非常宝贵的.
我是关于查看文档的建议.它并不像看起来那么可怕.还有一些简短的提示:
scoped_ptr
- 超出范围时自动删除的指针.注意 - 没有可能的分配,但没有引入任何开销
intrusive_ptr
- 引用计数指针,没有开销smart_ptr
.但是,对象本身存储引用计数
weak_ptr
- 与shared_ptr
处理导致循环依赖的情况一起工作(阅读文档,并在谷歌上搜索漂亮的图片;)
shared_ptr
- 智能指针的通用,最强大(和重量级)(来自boost提供的)
还有旧的auto_ptr
,确保当控件离开范围时,它指向的对象会自动销毁.然而,它具有与其他人不同的复制语义.
unique_ptr
- 将带有C++ 0x
回复编辑: 是的