3 回答
TA贡献1794条经验 获得超7个赞
智能指针的基本属性
当您拥有可以分配每个智能指针的属性时,这很容易。有三个重要的属性。
根本没有所有权
所有权转让
所有权份额
第一个意味着智能指针不能删除对象,因为它不拥有它。第二个意味着只有一个智能指针可以同时指向同一个对象。如果要从函数返回智能指针,则所有权将转移到返回的智能指针。
第三个意味着多个智能指针可以同时指向同一个对象。这也适用于原始指针,但原始指针缺少一个重要特征:它们不定义它们是否拥有。如果每个所有者放弃该对象,则共享所有权智能指针将删除该对象。这种行为恰好经常需要,因此共享拥有的智能指针广泛传播。
一些拥有智能指针既不支持第二个也不支持第三个。因此,它们不能从函数返回或传递到其他地方。哪个最适合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_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遵循的语义,但由于缺少对移动的本机支持,它无法提供它们而没有陷阱。unique_ptr将自动从临时的其他unique_ptr中窃取资源,这是移动语义的关键特性之一。auto_ptr将在下一个C ++标准版本中弃用,而不是unique_ptr。C ++ 1x还允许填充仅可移动但不可复制到容器中的对象。因此,您可以将unique_ptr填充到矢量中。如果你想了解更多相关信息,我会在这里停下来并引用你一篇关于此的精彩文章。
TA贡献1783条经验 获得超4个赞
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 }
当您必须使用第三方智能ptr时,通常会使用intrusive_ptr。它将调用一个自由函数来添加和减少引用计数。请参阅提升文档的链接以获取更多信息。
TA贡献1820条经验 获得超2个赞
不要忽视boost::ptr_container
任何有关boost智能指针的调查。在例如std::vector<boost::shared_ptr<T> >
太慢的情况下,它们可能是非常宝贵的。
- 3 回答
- 0 关注
- 522 浏览
添加回答
举报