【问题标题】:Should i always use smart pointer in C++ 11 [duplicate]我应该总是在 C++ 11 中使用智能指针吗?
【发布时间】:2014-03-11 04:28:53
【问题描述】:

从 c++ 11 开始,我可以在不创建和删除原始指针的情况下编写代码。 但这是正确的方法吗?我应该始终使用智能指针(共享、唯一或弱指针)还是在某些情况下我应该自己删除对象?

【问题讨论】:

  • 有人建议我问另一个问题。我没有收到原始问题的答案
  • 实际上,您的另一个问题已作为重复问题关闭。副本中的答案非常好。
  • 再来一次?严重地?您是一位经验丰富的用户(200 多个问题),学习做研究
  • 4 年了,你还在这样发帖?

标签: c++ c++11 shared-ptr


【解决方案1】:

很难想象您想要手动删除对象的情况,因此从这个意义上说,您的问题的答案是“是的,始终使用智能指针”。

但是,原始指针确实有另一个用例。智能指针都是关于赋予所有权语义。 unique_ptr 拥有它所指向的对象的独占所有权,并且会在指针超出范围时销毁该对象。 shared_ptr 实现共享所有权,当最后一个共享指针超出范围时,对象将被销毁。

原始指针在您想要指向一个对象而不表明任何类型的所有权的情况下仍然有用。您只是指向一个您知道存在的对象,并且其他人(拥有它)会在时机成熟时将其删除。

原始指针用于指向对象。智能指针用于拥有对象。

【讨论】:

  • 写得很好的代码中的大多数删除是delete this。这算作“手动删除”一个对象吗?如果不想显式控制对象的生命周期,首先要问的问题是:我为什么要动态分配它?
  • @JamesKanze:我还没有看到很多包含delete this 的“写得很好的”代码。而且我很确定我们不同意编写良好的 C++ 代码是什么。除此之外,我真的不知道如何回答你。我不确定您对对象生命周期的“显式控制”是什么意思。如果我使用unique_ptrshared_ptr,我是否有明确的控制权?我确切地控制它应该何时被删除,但我没有明确地将代码放在我想要删除它的站点上。我通常确实想要控制对象的生命周期。这就是我使用智能指针的原因。
  • 我也不确定您认为什么是“动态分配”。 std::vector 内部使用动态分配,但它对用户不直接可见。您是否建议我们甚至不应该这样做,而让应用程序完全依赖堆栈而不管您要分配的内存量是多少?
  • 最简单的方法就是举个例子。如果你有一个像BankAccount这样的类,它是一个实体对象,它支持不同的操作,比如depositwithdrawclose等。特别是close的操作会使一定数量的验证,然后,如果一切正常,请执行 delete this; 关闭帐户。对象生存期由程序规范确定,以响应外部事件或请求。这是处理实体对象的逻辑方式,很少有其他对象应该动态分配(至少在应用程序级别)。
  • 关于std::vector:大小不确定的对象,如向量、字符串和图形在其实现中使用动态内存。他们的客户不应该看到它,当然,他们将管理内存并酌情删除它(最迟在他们的析构函数中)。但您肯定不建议在std::vector 中使用智能指针来存储内存。 (当然,std::vector 是一个特例,因为它把分配和初始化分开了,实现代码可能从不使用delete 操作符。)
【解决方案2】:

在极少数情况下您想要使用智能 指针。在大多数应用程序中,大多数删除将是 delete this,或者如果应用程序是事务性的,则 事务管理器将负责删除。在案件 如果这不适用,您通常不想使用 动态分配开始。大约只有你会 使用智能指针:

  • 由于某种原因,您无法完全制作对象 在构造函数中操作,但必须跟进 激活之前的附加操作。在这种情况下,它使 将其保存在 std::unique_ptr 中直到对象 完全激活,然后拨打release

  • 您确实需要值语义,但您还需要 多态性。在这种情况下,使用某种共享指针。 (但要小心循环。)如果对象是可变的,也要小心, 因为你最终会得到引用语义。

  • 您确实需要值语义(带有深拷贝),但是 profiler 显示复制的成本太高,你可能 还可以考虑某种共享指针。这有它的 危险,但对于大块的不可变数据,可能是一个很好的 解决方案。

但对于初学者,您应该始终问自己:为什么 我动态分配这个对象。最常见的有效 原因是它是一个实体对象,定义了生命周期 通过程序逻辑(即它的生命周期由于某些原因而结束 外部事件)。在这种情况下,智能指针会导致更多 比他们解决的问题。

【讨论】:

  • 没有动态分配?您将如何为视频游戏加载一堆资产?如果您申请 RAII,那么您的第一点就是错误的。
  • @Syl 我没有说没有动态分配。我说你只在适当的时候使用动态分配。在视频游戏中,会有很多动态分配的对象:代表玩家的对象,以及各种对象。但它们都是实体对象;你不会用智能指针来管理它们(或者至少,不是我见过的任何智能指针)。如果怪物用破坏你盔甲的东西袭击你,你的盔甲应该被摧毁,无论如何;你不希望它到处乱跑,因为仍然有一个共享指针指向它。
  • @Syl 我的第一点正是 RAII。只要“资源”(新创建的对象)是短暂的,并且在超出范围时应该被破坏,您就可以将其保存在智能指针中。当然,一旦它不再是短暂的,并且必须超出范围,你必须将它从智能指针中取出,因为 RAII(尽管它的名字,更关心自动销毁)不再适用。
猜你喜欢
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-22
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 2014-10-01
相关资源
最近更新 更多