什么时候应该让课程不可复制?

pig*_*d10 4 c++ class copy-constructor assignment-operator

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

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

但是,我听到了一些反对这一点的论点:

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

遵循本指南的正面/负面是什么?是否有任何标准的"经验法则"使类不可复制?创建新类时我应该考虑什么?

Jos*_*eld 6

我的建议有两个问题:

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

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

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

这个建议似乎是基于这样一种信念,即程序员默认按值传递对象,当对象足够复杂时,这可能很昂贵.这不再是真的.您应该默认为按价值计算为传递对象,当你需要的对象的副本,而且也没有理由去害怕这一切-在许多情况下,移动构造函数将被用来代替,这是几乎总是一个固定时间操作.

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

  1. 我需要这个对象的副本吗?
  2. 我需要修改这个对象吗?
  3. 对象的生命周期是多少?
  4. 对象是可选的吗?

这些问题应该与您编写的每种类型(参数,返回值,变量,等等)一起询问.您应该找到很多用于按值传递对象的用法,这些用法不会因复制而导致性能下降.

如果你遵循良好的C++编程实践,你的拷贝构造函数将是无bug的,所以这不应该是一个问题.事实上,许多类只能使用默认的复制/移动构造函数.如果一个类拥有动态分配的资源并且您正确使用智能指针,那么实现复制构造函数通常就像从指针复制对象一样简单 - 没有太大的空间来容纳错误.

当然,谷歌的这个建议是为那些致力于代码的人们确保整个代码库的一致性.没关系.但是,我建议不要盲目地将它全部用于现代C++项目.

  • 我不建议在这么深的问题中尽早接受答案.一些更好的答案可能需要一些时间才能到达. (3认同)