你应该在什么时候使一个类不可压缩
When should you make a class uncopyable?
根据谷歌风格指南,"很少有类需要可复制。大多数应该既没有复制构造函数也没有赋值运算符">
他们建议您使类不可复制(也就是说,不给它一个复制构造函数或赋值运算符),而是建议在大多数情况下通过引用或指针传递,或者使用不能隐式调用的clone()方法。
然而,我听到了一些反对这一点的论点:
- 访问引用(通常)比访问值慢
- 在某些计算中,我可能希望保持原始对象的原样,只返回更改后的对象
- 我可能想将计算的值作为本地对象存储在函数中并返回它,如果我通过引用返回它,我就无法做到这一点
- 如果一个类足够小,则通过引用传递的速度会较慢
遵循本指南的积极因素/消极因素是什么?是否有任何标准";经验法则;让类不可压缩?创建新类时应该考虑什么?
我对他们的建议有两个问题:
-
它不适用于现代C++,忽略了移动构造函数/赋值运算符,因此假设按值获取对象(以前会复制)通常效率低下。
-
它不相信程序员会做正确的事情并适当地设计他们的代码。相反,它限制了程序员,直到他们被迫打破规则。
您的类是否应该是可复制的、可移动的、两者都不应该是基于类本身的用途的设计决策。例如,std::unique_ptr
是一个很好的类的例子,它只应该是可移动的,因为复制它会使其整个目的无效。当你设计一个课程时,问问自己复制它是否有意义。大多数时候答案都是肯定的。
这个建议似乎是基于这样一种信念,即程序员默认按值传递对象,当对象足够复杂时,这可能会很昂贵。这已经不是事实了。当需要对象的副本时,应该默认按值传递对象,没有理由害怕这一点-在许多情况下,将使用move构造函数,这几乎总是一个恒定的时间操作。
同样,选择如何传递对象是一个设计决策,应该受到许多因素的影响,例如:
- 我需要这个对象的副本吗
- 我需要修改这个对象吗
- 物体的寿命是多少
- 这个对象是可选的吗
这些问题应该针对您编写的每种类型(参数、返回值、变量等)提出。您应该会发现按值传递对象有很多用途,不会因为复制而导致性能下降。
如果您遵循良好的C++编程实践,那么您的复制构造函数将是无错误的,所以这不应该是一个问题。事实上,许多类可以只使用默认的复制/移动构造函数。如果一个类拥有动态分配的资源,并且您适当地使用了智能指针,那么实现复制构造函数通常就像从指针中复制对象一样简单——没有太大的漏洞空间。
当然,谷歌的这条建议是给那些编写代码的人的,以确保整个代码库的一致性。没关系。然而,我不建议在现代C++项目中盲目地采用它的全部内容。
- 我想通过带有C++和Python的插件创建一个可扩展的应用程序
- 程序在使用 system() 启动另一个可执行文件时停止
- 函数可以应用于 std::optional,并返回一个可选值吗?
- 有一个可迭代的容器,其中的成员在编译时是已知的
- 如何拥有一个可由多种语言调用的C++库
- 从c++11 time_t创建一个可转换为.net DateTime的字符串
- 只有一个可执行文件即可进行跨平台 SIMD 调用?
- 构建一个可执行文件,如果是单个 cpp 文件
- 是否可以在C++中制作一个可调用自身的实函数类型?
- 如何维护类成员的顺序,并且仍然有一个可工作的构造函数
- 如何在C 中提供一个可呼叫的对象访问,例如lambda
- C++将各种资源文件链接到一个可执行文件中
- 如何在 ubuntu 上将可执行文件注入另一个可执行文件
- 'Continuous' C++一个可执行文件的输出作为另一个程序的输入
- 程序如何创建另一个可执行文件
- 是否有一个可视化 c++ 预定义的预处理器宏,让您知道编译器何时优化
- 使用一个可选参数获取两个参数到main
- 具有2个值的容器(对于每个浮点数一个可操作的整数)
- 用cpp、python和csv文件制作一个可执行文件
- 从Ubuntu到Debian运行一个可执行文件