你应该在什么时候使一个类不可压缩

When should you make a class uncopyable?

本文关键字:一个 可压缩 什么时候      更新时间:2023-10-16

根据谷歌风格指南,"很少有类需要可复制。大多数应该既没有复制构造函数也没有赋值运算符">

他们建议您使类不可复制(也就是说,不给它一个复制构造函数或赋值运算符),而是建议在大多数情况下通过引用或指针传递,或者使用不能隐式调用的clone()方法。

然而,我听到了一些反对这一点的论点:

  • 访问引用(通常)比访问值慢
  • 在某些计算中,我可能希望保持原始对象的原样,只返回更改后的对象
  • 我可能想将计算的值作为本地对象存储在函数中并返回它,如果我通过引用返回它,我就无法做到这一点
  • 如果一个类足够小,则通过引用传递的速度会较慢

遵循本指南的积极因素/消极因素是什么?是否有任何标准";经验法则;让类不可压缩?创建新类时应该考虑什么?

我对他们的建议有两个问题:

  1. 它不适用于现代C++,忽略了移动构造函数/赋值运算符,因此假设按值获取对象(以前会复制)通常效率低下。

  2. 它不相信程序员会做正确的事情并适当地设计他们的代码。相反,它限制了程序员,直到他们被迫打破规则。

您的类是否应该是可复制的、可移动的、两者都不应该是基于类本身的用途的设计决策。例如,std::unique_ptr是一个很好的类的例子,它只应该是可移动的,因为复制它会使其整个目的无效。当你设计一个课程时,问问自己复制它是否有意义。大多数时候答案都是肯定的。

这个建议似乎是基于这样一种信念,即程序员默认按值传递对象,当对象足够复杂时,这可能会很昂贵。这已经不是事实了。当需要对象的副本时,应该默认按值传递对象,没有理由害怕这一点-在许多情况下,将使用move构造函数,这几乎总是一个恒定的时间操作。

同样,选择如何传递对象是一个设计决策,应该受到许多因素的影响,例如:

  1. 我需要这个对象的副本吗
  2. 我需要修改这个对象吗
  3. 物体的寿命是多少
  4. 这个对象是可选的吗

这些问题应该针对您编写的每种类型(参数、返回值、变量等)提出。您应该会发现按值传递对象有很多用途,不会因为复制而导致性能下降。

如果您遵循良好的C++编程实践,那么您的复制构造函数将是无错误的,所以这不应该是一个问题。事实上,许多类可以只使用默认的复制/移动构造函数。如果一个类拥有动态分配的资源,并且您适当地使用了智能指针,那么实现复制构造函数通常就像从指针中复制对象一样简单——没有太大的漏洞空间。

当然,谷歌的这条建议是给那些编写代码的人的,以确保整个代码库的一致性。没关系。然而,我不建议在现代C++项目中盲目地采用它的全部内容。