复制构造函数传统上在 C++ 程序中无处不在。但是,我怀疑自 C++11 以来是否有充分的理由这样做。
即使程序逻辑不需要复制对象,复制构造函数(通常是默认的)也经常被包含在对象重新分配的唯一目的中。如果没有复制构造函数,您将无法将对象存储在 a 中std::vector
,甚至无法从函数中返回对象。
但是,从 C++11 开始,移动构造函数一直负责对象重新分配。
复制构造函数的另一个用例是简单地复制对象。但是,我非常相信.copy()
or.clone()
方法比复制构造函数更适合该角色,因为...
复制对象并不常见。当然,对象的接口有时需要包含“复制自己”方法,但只是有时。在这种情况下,显式优于隐式。
有时一个对象可能会暴露几个不同
.copy()
的类似方法,因为在不同的上下文中,可能需要以不同的方式创建副本(例如更浅或更深)。在某些情况下,我们希望
.copy()
方法执行与程序逻辑相关的重要事情(增加一些计数器,或者可能为副本生成一个新的唯一名称)。我不会接受任何在复制构造函数中具有非显而易见逻辑的代码。最后但同样重要的
.copy()
是,如果需要,方法可以是虚拟的,从而可以解决切片问题。
我真正想要使用复制构造函数的唯一情况是:
- 可复制资源的 RAII 句柄(很明显)
- 旨在用作内置类型的结构,如数学向量或矩阵 -
仅仅是因为它们经常被复制并且vec3 b = a.copy()
过于冗长。
旁注:我已经考虑过CAS需要复制构造函数这一事实,但是
operator=(const T&)
基于完全相同的推理,我认为需要 CAS 是多余的;
.copy()
如果您真的需要, +operator=(T&&) = default
将是首选。)
对我来说,这足以激励我在T(const T&) = delete
任何地方默认使用并.copy()
在需要时提供一种方法。(也许也private T(const T&) = default
只是为了能够编写copy()
或virtual copy()
没有样板。)
问:上述推理是否正确,或者我错过了逻辑对象实际需要或以某种方式受益于复制构造函数的任何充分理由?
具体来说,移动构造函数完全接管了 C++11 中对象重新分配的责任,我是否正确?当对象需要在内存中的其他位置移动而不改变其状态时,我非正式地使用“重新分配”来处理所有情况。