智能指针的基本属性
当您拥有可以分配每个智能指针的属性时,这很容易。 有三个重要的属性。
根本没有所有权
所有权转让
所有权份额
第一个意味着智能指针不能删除对象,因为它不拥有它。 第二个意味着只有一个智能指针可以同时指向同一个对象。 如果要从函数返回智能指针,则所有权将转移到返回的智能指针。
第三个意味着多个智能指针可以同时指向同一个对象。 这也适用于原始指针,但原始指针缺少一个重要特征:它们不定义它们是否拥有。 如果每个所有者放弃该对象,则共享所有权智能指针将删除该对象。 这种行为恰好需要经常使用,因此共享拥有的智能指针广泛传播。
一些拥有智能指针既不支持第二个也不支持第三个。 因此,它们不能从函数返回或传递到其他地方。 哪个最适合unique_ptr目的,智能指针保持在本地并且刚刚创建,因此它在超出范围后释放对象。
可以通过拥有复制构造函数来实现所有权共享。 这自然会复制一个智能指针,副本和原始文件都将引用同一个对象。 所有权的转移当前并不能真正用C ++实现,因为没有办法将某些东西从一个对象转移到另一个对象支持的语言:如果你试图从一个函数返回一个对象,那么正在发生的事情是该对象被复制。 因此,实现所有权转移的智能指针必须使用复制构造函数来实现所有权的转移。 然而,这反过来又破坏了它在容器中的使用,因为需求声明了容器元素的复制构造函数的某种行为,这与这些智能指针的所谓“移动构造函数”行为不相容。
C ++ 1x通过引入所谓的“移动构造函数”和“移动赋值运算符”为所有权转移提供本机支持。 它还附带了一个名为unique_ptr的所有权转让智能指针。
分类智能指针
unique_ptr是一个既不可转移也不可共享的智能指针。 它只是在本地需要分配内存时才可用,但是当它超出范围时确保它再次被释放。 但如果您愿意,它仍然可以与另一个scoped_ptr交换。
unique_ptr是一个共享所有权的智能指针(上面第三种)。 它是引用计数,因此它可以看到它的最后一个副本超出范围,然后释放所管理的对象。
unique_ptr是一个非拥有的智能指针。 它用于引用托管对象(由shared_ptr管理),而不添加引用计数。 通常,您需要从shared_ptr中获取原始指针并复制它。 但这不安全,因为你无法检查对象何时被实际删除。 因此,weak_ptr通过引用shared_ptr管理的对象来提供方法。 如果您需要访问该对象,您可以锁定它的管理(以避免在另一个线程中,shared_ptr在您使用该对象时释放它)然后使用它。 如果weak_ptr指向已删除的对象,它将通过抛出异常来通知您。 当你有一个循环引用时,使用weak_ptr是最有益的:引用计数不能轻易应对这种情况。
unique_ptr类似于shared_ptr,但它不会将引用计数保留在shared_ptr中,而是将计数递增/递减到需要由托管对象定义的某些辅助函数。 这样做的好处是,已经引用的对象(具有由外部引用计数机制递增的引用计数)可以填充到intrusive_ptr中 - 因为引用计数不再是智能指针内部的,但智能指针使用现有的 参考计数机制。
unique_ptr是所有权指针的转移。 你无法复制它,但你可以使用C ++ 1x的移动构造函数来移动它:
unique_ptr p(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填充到矢量中。 如果你想了解更多相关信息,我会在这里停下来并引用你一篇关于此的精彩文章。