C++完全是关于内存所有权
Aka" Ownership Semantics "
一块动态分配的内存的所有者负责释放该内存.所以这个问题真的变成了拥有记忆的人.
在C++中,所有权都是由RAW指针包含在内部的类型记录的,因此在一个好的(IMO)C++程序中,很少见[RARE并非永远]看到RAW指针传递(因为RAW指针没有推断的所有权因此我们不能告诉谁拥有记忆,因此如果没有仔细阅读文件,你无法分辨谁负责所有权).
相反,很少看到RAW指针存储在类中,每个RAW指针都存储在自己的SMART指针包装器中.(注意:如果你没有一个对象,你不应该存储它,因为你不知道什么时候它会超出范围并被销毁.)
所以问题是:
人们遇到什么类型的所有权语义?
使用哪些标准类来实现这些语义?
你认为它们在哪些情况下有用?
让我们为每个答案保留一种语义所有权,这样他们就可以单独上下投票
摘要:从概念上讲,智能指针很简单,而且简单易用.我已经看过许多尝试过的实现,但总是以某种方式打破它们,这对于随意使用和示例来说并不明显.因此,我建议始终使用经过良好测试的"智能指针",而不是自己动手.std :: auto_ptr或其中一个提升智能指针似乎涵盖了我的所有需求.
单身人士拥有该物品.
但允许转让所有权.
用法:
======
这允许您定义显示所有权显式转移的接口.
单身人士拥有该物品.
不允许转让所有权.
用法:
======
用于显示明确的所有权.
对象将被析构函数或显式重置时销毁.
多个所有权.
这是一个简单的引用计数指针.当引用计数达到零时,对象被销毁.
用法:
======
当对象可以有多个owers,其生命周期无法在编译时确定.
与shared_ptr
在指针循环可能发生的情况下.
用法:
======
用于在仅循环维护共享引用计数时停止保留对象的周期.
在我看到的大多数模块中,默认情况下,假设接收指针没有接收所有权.实际上,放弃指针所有权的函数/方法都非常罕见,并且在其文档中明确表达了这一事实.
此模型假定用户仅是他/她明确分配的内容的所有者.其他所有内容都会自动处理(在范围退出处或通过RAII).这是一个类似C的模型,扩展的事实是大多数指针都由对象拥有,这些对象将自动或在需要时释放它们(主要是在所述对象破坏时),并且对象的生命持续时间是可预测的(RAII是你的朋友,再次).
在这个模型中,原始指针是自由流通的,并且大多数都没有危险(但如果开发人员足够聪明,他/她将尽可能使用引用).
原始指针
性病:: auto_ptr的
提高:: scoped_ptr的
在充满智能指针的代码中,用户可以希望忽略对象的生命周期.所有者永远不是用户代码:它是智能指针本身(RAII,再次).问题是与引用计数智能指针混合的循环引用可能是致命的,所以你必须同时处理共享指针和弱指针.因此你仍然需要考虑所有权(弱指针很可能指向任何东西,即使它优于原始指针也是它可以告诉你的).
提高:: shared_ptr的
提高:: weak_ptr的
无论我描述的模型,除非异常,接收指针都没有获得它的所有权,知道谁拥有谁仍然是非常重要的.即使对于大量使用引用和/或智能指针的C++代码也是如此.
对我来说,这三种类型涵盖了我的大部分需求:
shared_ptr
- 当计数器达到零时,引用计数,解除分配
weak_ptr
- 与上面相同,但它是a的"奴隶" shared_ptr
,不能解除分配
auto_ptr
- 当创建和释放发生在同一个函数内部时,或者当对象必须被认为只有一个所有者时.当您将一个指针指定给另一个指针时,第二个指针会从第一个指定"窃取"该对象.
我有自己的实现,但它们也可用于Boost
.
我仍然通过引用传递对象(const
只要有可能),在这种情况下,被调用的方法必须假定对象仅在调用期间处于活动状态.
还有另一种我使用的指针,我称之为hub_ptr.当你拥有一个必须可以从嵌套在其中的对象访问的对象时(通常作为一个虚拟基类).这可以通过传递weak_ptr
给他们来解决,但它本身没有shared_ptr
.因为它知道这些对象不会比他长寿,所以它会将hub_ptr传递给它们(它只是常规指针的模板包装器).
没有共享所有权.如果您这样做,请确保它只包含您无法控制的代码.
这解决了100%的问题,因为它迫使你理解一切如何相互作用.