Should i always use smart pointer in C++ 11
从C++ 11我可以编写代码而不创建和删除原始指针。但这是正确的方法吗?我应该始终使用智能指针(共享、唯一或弱指针)还是在某些情况下应该自己删除对象?
- 有人建议我再问一个问题。我没有收到原始问题的答案
- 事实上,你的另一个问题是作为一个副本结束的。副本中的答案很好。
- 再一次?真的吗?你是一个非常有经验的用户(200 +问题),学习做研究
- 4年过去了,你还在这样发帖?
很难想象您想要手动删除对象的情况,因此从这个意义上来说,问题的答案是"是的,总是使用智能指针"。
但是,原始指针确实有另一个用例。智能指针都是关于授予所有权语义的。unique_ptr拥有它指向的对象的独占所有权,当指针超出范围时,它将销毁该对象。shared_ptr实现共享所有权,当最后一个共享指针超出范围时,对象将被销毁。
对于希望指向对象而不指示任何所有权的情况,原始指针仍然有用。你只是指向一个你知道存在的对象,而其他人(拥有它的人)会在时间到来时删除它。
原始指针用于指向对象。智能指针用于拥有对象。
- 在编写良好的代码中,大多数删除都是delete this。这是否算作"手动删除"对象?如果您不希望显式地控制对象的生存期,那么首先要问的问题是:为什么要动态地分配它?
- @Jameskanze:我没有看到很多"编写良好"的代码包含delete this。我确信我们对C++编写的代码有不同意见。除此之外,我真的不知道怎么回答你。我不确定你所说的"明确控制"一个对象的生命周期是什么意思。如果我使用unique_ptr或shared_ptr,我是否有明确的控制权?我精确地控制何时应该删除它,但是我不明确地将代码放在我想要删除它的站点上。我通常想控制一个对象的生命周期。这就是我使用智能指针的原因。
- 我也不确定你到底认为什么是"动态分配"。std::vector内部使用动态分配,但用户无法直接看到它。您是否建议我们甚至不应该这样做,让应用程序完全依赖于堆栈,而不管您要分配多少内存?
- 最简单的方法是举个例子。如果你有一个像BankAccount这样的类,它是一个支持不同操作的实体对象,比如deposit、withdraw、close等,特别是close操作会进行一定数量的验证,如果一切正常,通过delete this;关闭账户。对象生存期由程序规范决定,以响应外部事件或请求。这是处理实体对象的逻辑方法,并且很少有其他对象应该被动态分配(至少在应用程序级别)。
- 关于std::vector:不确定大小的对象,如向量、字符串和图形将在它们的实现中使用动态存储器。他们的客户不应该看到它,当然,他们会管理内存,并适当地删除它(最新的,在析构函数中)。但是你肯定不会建议在EDCOX1的4内存中使用智能指针来存储内存。(当然,std::vector是一种特殊情况,因为它将分配和初始化分开,并且实现代码可能永远不会使用delete操作符。)
很少有情况下你想使用智能指针。在大多数应用程序中,大多数删除将delete this,或者如果应用程序是事务性的,则事务管理器将负责删除。在案件中如果这不适用,您通常不想使用要开始的动态分配。只有几次你会使用智能指针:
由于某些原因,您无法使对象完全在构造函数中操作,但必须跟进活动之前的其他动作。在这种情况下,它使将其保持在EDCOX1×3中,直到对象是完全激活,然后调用release。
你真的想要值语义,但你也需要多态性。在这种情况下,使用某种共享指针。(但要注意周期。)如果物体是可变的,也要注意,因为您将以引用语义结束。
您确实需要值语义(使用深度复制),但是探查器显示复制成本太高,您可能还要考虑某种共享指针。这有它的危险,但对于大量不可变的数据,可能是一个好的解决方案。
但首先,你应该问问自己:为什么我动态地分配这个对象。最频繁的有效原因是它是一个实体对象,定义了生存期按程序逻辑(即,由于某些外部事件)。在这种情况下,智能指针将导致更多他们解决不了的问题。
- 没有动态分配?如何为一个电子游戏加载一堆资产?如果你申请了RAII,你的第一点就错了。
- @我没有说没有动态分配。我说过,只有在适当的时候才使用动态分配。在电子游戏中,会有很多动态分配的对象:代表玩家的对象和各种对象。但它们都是实体对象;您不会用智能指针(或者至少,我见过的任何智能指针)来管理它们。如果一个怪物用破坏你盔甲的东西攻击你,不管怎样,你的盔甲应该被摧毁;你不想让它在你周围徘徊,因为仍然有一个共用的指针指向它。
- @西尔和我的第一点正是雷伊。只要"资源"(新创建的对象)是短暂的,并且如果超出范围应该被销毁,那么您就将它保存在一个智能指针中。当然,一旦它不再是短暂的,并且必须超出范围,您就必须将它从智能指针中取出,因为raii(尽管它的名字更关心自动销毁)不再适用。