C++(14)和手动内存管理

Fer*_*eak 30 c++ memory-management c++14

我刚收到一条评论,比如说

问题是手动内存管理.delete在用户代码中没有位置,从C++ 14开始,也没有new

有人可以解释一下为什么吗?

Kon*_*lph 37

警告:我坚持这个答案,因为我认为它提出了一个最佳实践,可以提高~95%的C++代码 - 可能更多.也就是说,请阅读完整的评论,以讨论一些重要的警告.

由于这是我的评论,这是我的演讲解释这一点.

简而言之:

[原始]指针必须.不.拥有.资源.

因为我们有管理这导致错误更少的资源,更短,更可读的代码和更高的更好的方式这是容易出错和不必要的信心在代码的正确性.从经济角度来说:它们的成本更低.

关于我所做的评论,更具体一点:

从C++ 11开始(现在已经有两年了,在所有现代编译器的相关部分中实现),手动删除内存是完全没必要的(除非你编写非常低级的内存处理代码),因为你总是可以使用智能而是指针,通常甚至不需要它们(参见演示文稿).但是,C++ 11仍然需要new在实例化新的时使用std::unique_ptr.在C++ 14中,该函数std::make_unique使得这种使用变得new不必要.因此,它也不再需要了.

仍然可以说是放置new代码的地方,但这是(a)与正常情况完全不同的情况new,即使语法相似,并且(b)在大多数情况下可以通过使用allocator::construct函数来替换.


詹姆斯已经指出了这个规则的一个例外,我真实地忘记了这个例子:当一个物体管理自己的生命时.我会去上肢体和说,这是不是在大多数情况下一个常见的成语,因为对象的生命时间可以随时在外部管理.但是,在某些应用程序中,将对象与其余代码分离并让它自行管理可能是有益的.在这种情况下,您需要动态分配对象并使用它来释放它delete this.

  • @Konrad:我想我之前和詹姆斯讨论过这种事情.在我看来,他主要以一种我认为不是真正的标准(不打算作为批评)的风格进行编程.在这种风格中,实体对象经常(总是?)在智能指针和容器封装的意义上不被其他实体"拥有".这有点像编写状态机来代替结构化控制流.这是程序结构的一个属性,即实体在正确的时间被销毁,而不是直接归因于释放它们的特定所有者(甚至是共享所有者组). (5认同)
  • @James幻灯片显示常规使用动态分配的情况*吨*.幻灯片虽然没有声明完整性,但很容易在典型代码中覆盖99%的"新"用例.然而,除了幻灯片之外,我*会*声明完整性(请参阅上面的评论).你为什么不说出为什么坚持智能指针是一种反模式呢?(但请注意,我并不坚持这一点,相反,我坚持自动资源管理 - 这比智能指针更常见,我个人很少使用它). (4认同)
  • @KonradRudolph在适当的地方使用智能指针不是反模式.反模式试图在您使用动态分配的任何地方使用它们. (3认同)
  • @James幻灯片故意煽动.他们是*chrissake的演示幻灯片*,这是他们的工作.原因是,大多数C++(甚至是经验丰富的)程序员都过度依赖手动内存管理,这让我非常疯狂,因为它会严重影响代码质量. (3认同)
  • @KerrekSB我做.它违反了SRP.我通过`std :: unique_ptr <T []>`实现`vector`,我觉得这应该是实现它的规范方式.另见Martinho有影响力的[Zero of Zero文章](http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html).正如我之前所说,非拥有原始指针很好. (3认同)
  • @KonradRudolph,如果你想正确处理预分配,我很确定你不能. (3认同)
  • @KerrekSB不,我在该声明中非常包括私人类成员.我做了一个例外,只有一个例外:实现自己的智能指针时.其他一切都将无法通过我的代码审查. (2认同)
  • @KonradRudolph无论如何,坚持在各地使用智能指针是一个主要的反模式. (2认同)
  • @KerrekSB:从节点到其父节点的指针是非拥有的,因此不能作为Konrad所说的任何反例.在"vector"的情况下,我想象一个精心设计的删除器.它会查询向量的大小,因此它知道要销毁多少元素,以及用于销毁对象和释放块的分配器.或者也许容器的析构函数可以调整为0,这样智能指针只需要担心块而不是元素.顺便说一下标准容器*不要使用placement new,它们在分配器上使用`construct`.当然它提出了同样的问题;-) (2认同)
  • 如何使用没有原始指针的Qt进行编码? (2认同)