智能指针的效率如何?
How efficient smart pointers are?
我知道,std::shared_ptr
使用引用计数,所以它有复制和移动语义,另一方面 std::unique_ptr
(因此名称唯一)只有移动语义,所以试图复制它是编译错误。
但是,我不太清楚这有多大意义。在大多数情况下,我可以简单地使用 std::shared_ptr
而不是 std::unique_ptr
,还是应该尽可能使用 std::unique_ptr
,因为它不需要处理引用计数,因此效率更高?
此外,我知道智能指针在处理异常安全等问题时很有用,但它们是否可以普遍取代传统的 T*
指针?
尽可能使用智能指针而不是传统的 T*
指针是一种好的编程习惯吗?
shared_ptr
的问题是,afaik,引用计数是一个原子函数,这意味着它不仅计算引用,而且还具有锁定功能以确保该函数是原子的。所以在这一点上,是的,当您只需要移动功能时,unique_ptr
更适合使用。
就个人而言,我不经常使用 shared_ptr
,大多数普通指针就足够了。恕我直言,智能指针只会鼓励在内存管理中变得懒惰。我在一些项目中,智能指针只会在退出程序时导致竞争条件,因为没有人知道销毁的顺序,而且这些指针相互引用。对于我自己,我只在我的一个库将指针指向外部时才使用它们,当它们被删除时(或以何种顺序)它是无关紧要的。
A shared_ptr 具有指针本身的 construction/destruction 的额外成本,如果传递给函数,加上引用计数机制。
不要听任何人说智能指针总是可行的,也不要听那些说原始指针总是更好的人。
有些情况下智能指针有意义,有些情况下原始指针更可取。
如需更详细全面的阅读,我建议您访问:
http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
它涵盖了您提出的所有要点,而且大部分内容都很容易阅读。
经验法则是:
- 如果可以,直接或通过引用使用基于堆栈的对象,而不是使用指针。
- 否则,如果您不必处理共享所有权(通常不需要),请使用 unique_ptr - 它不仅更快,而且更安全(无循环引用)。
- 否则,如果您确实拥有共享所有权,请使用 shared_ptr
原始指针在某些情况下是可以的,当它们不带有所有权时——例如作为函数的输入参数:
void draw (const shape* sh) {
sh->draw();
}
...
std::unique_ptr<shape> ptr(new triangle);
draw(ptr.get());
shared_ptr
意味着围绕资源的所有权规则很复杂。了解它们需要追踪一般情况下所有 shared_ptr
的生命周期。
unique_ptr
意味着围绕资源的所有权规则非常简单。
两者都执行一套所有权规则,但 unique_ptr
的规则简单且本地化,shared_ptr
的规则复杂且非本地化。如果你处在随便在两者之间做出选择的情况下,那么你就不会以他们应得的重力来对待生活问题。
如果你有一个类似指针的资源,它的生命周期应该被简单地控制,或者甚至在一些中心位置(类型方面)周围有复杂的逻辑,使用 unique_ptr
。原始指针的成本是最小的,并且它添加(强制)文档表明这是指向此资源的 "owning" 指针。
如果您必须有一个资源,其生命周期是一堆其他对象的生命周期的并集,所有这些对象的生命周期都不相关,shared_ptr
可以是经过考虑的。如果您的情况如此复杂以至于可能形成循环,那么天真 shared_ptr
use 不再是一个实用的选择。
shared_ptr
和 weak_ptr
也可以用作分布式生命周期通知系统,其中中央位置存储一个(大部分是唯一的)shared_ptr
,而客户端存储 weak_ptr
s。本地(非存储)shared_ptr
s 是从 weak_ptr
s 创建的,以检查目标资源是否仍然存在,然后操作资源,然后丢弃本地 shared_ptr
。这里的目标是(以非语言强制的方式)使 unique_ptr
具有弱份额,因此关于生命周期的推理仅比 unique_ptr
情况稍微难一些。
shared_ptr
基本上 永远不会 "solves" 没有你证明它会解决你一生的问题。它可以使该证明的某些部分稍微容易一些。
您应该尽可能选择值而不是 std::unique_ptr
,选择 std::unique_ptr
而不是 std::shared_ptr
,但不是出于性能原因。是的,当涉及到 std::shared_ptr
时会有一些开销,因为它们在某种形式的原子计数器中使用,但这对于大多数应用程序来说可以忽略不计。
使用 std::unique_ptr
的主要原因是唯一性语义 - 当您(或其他人)阅读代码时,您会非常清楚对象的生命周期和所有权。这使得推理代码和发现 logical/performance 个问题变得更加容易。
PS: std::unique_ptr
与原始指针相比没有开销,但它有一些很大的优势。
我知道,std::shared_ptr
使用引用计数,所以它有复制和移动语义,另一方面 std::unique_ptr
(因此名称唯一)只有移动语义,所以试图复制它是编译错误。
但是,我不太清楚这有多大意义。在大多数情况下,我可以简单地使用 std::shared_ptr
而不是 std::unique_ptr
,还是应该尽可能使用 std::unique_ptr
,因为它不需要处理引用计数,因此效率更高?
此外,我知道智能指针在处理异常安全等问题时很有用,但它们是否可以普遍取代传统的 T*
指针?
尽可能使用智能指针而不是传统的 T*
指针是一种好的编程习惯吗?
shared_ptr
的问题是,afaik,引用计数是一个原子函数,这意味着它不仅计算引用,而且还具有锁定功能以确保该函数是原子的。所以在这一点上,是的,当您只需要移动功能时,unique_ptr
更适合使用。
就个人而言,我不经常使用 shared_ptr
,大多数普通指针就足够了。恕我直言,智能指针只会鼓励在内存管理中变得懒惰。我在一些项目中,智能指针只会在退出程序时导致竞争条件,因为没有人知道销毁的顺序,而且这些指针相互引用。对于我自己,我只在我的一个库将指针指向外部时才使用它们,当它们被删除时(或以何种顺序)它是无关紧要的。
A shared_ptr 具有指针本身的 construction/destruction 的额外成本,如果传递给函数,加上引用计数机制。
不要听任何人说智能指针总是可行的,也不要听那些说原始指针总是更好的人。 有些情况下智能指针有意义,有些情况下原始指针更可取。
如需更详细全面的阅读,我建议您访问: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
它涵盖了您提出的所有要点,而且大部分内容都很容易阅读。
经验法则是:
- 如果可以,直接或通过引用使用基于堆栈的对象,而不是使用指针。
- 否则,如果您不必处理共享所有权(通常不需要),请使用 unique_ptr - 它不仅更快,而且更安全(无循环引用)。
- 否则,如果您确实拥有共享所有权,请使用 shared_ptr
原始指针在某些情况下是可以的,当它们不带有所有权时——例如作为函数的输入参数:
void draw (const shape* sh) {
sh->draw();
}
...
std::unique_ptr<shape> ptr(new triangle);
draw(ptr.get());
shared_ptr
意味着围绕资源的所有权规则很复杂。了解它们需要追踪一般情况下所有 shared_ptr
的生命周期。
unique_ptr
意味着围绕资源的所有权规则非常简单。
两者都执行一套所有权规则,但 unique_ptr
的规则简单且本地化,shared_ptr
的规则复杂且非本地化。如果你处在随便在两者之间做出选择的情况下,那么你就不会以他们应得的重力来对待生活问题。
如果你有一个类似指针的资源,它的生命周期应该被简单地控制,或者甚至在一些中心位置(类型方面)周围有复杂的逻辑,使用 unique_ptr
。原始指针的成本是最小的,并且它添加(强制)文档表明这是指向此资源的 "owning" 指针。
如果您必须有一个资源,其生命周期是一堆其他对象的生命周期的并集,所有这些对象的生命周期都不相关,shared_ptr
可以是经过考虑的。如果您的情况如此复杂以至于可能形成循环,那么天真 shared_ptr
use 不再是一个实用的选择。
shared_ptr
和 weak_ptr
也可以用作分布式生命周期通知系统,其中中央位置存储一个(大部分是唯一的)shared_ptr
,而客户端存储 weak_ptr
s。本地(非存储)shared_ptr
s 是从 weak_ptr
s 创建的,以检查目标资源是否仍然存在,然后操作资源,然后丢弃本地 shared_ptr
。这里的目标是(以非语言强制的方式)使 unique_ptr
具有弱份额,因此关于生命周期的推理仅比 unique_ptr
情况稍微难一些。
shared_ptr
基本上 永远不会 "solves" 没有你证明它会解决你一生的问题。它可以使该证明的某些部分稍微容易一些。
您应该尽可能选择值而不是 std::unique_ptr
,选择 std::unique_ptr
而不是 std::shared_ptr
,但不是出于性能原因。是的,当涉及到 std::shared_ptr
时会有一些开销,因为它们在某种形式的原子计数器中使用,但这对于大多数应用程序来说可以忽略不计。
使用 std::unique_ptr
的主要原因是唯一性语义 - 当您(或其他人)阅读代码时,您会非常清楚对象的生命周期和所有权。这使得推理代码和发现 logical/performance 个问题变得更加容易。
PS: std::unique_ptr
与原始指针相比没有开销,但它有一些很大的优势。