Nicol Bolas在 SO中的回答中写道:
在许多情况下允许发生复制省略。然而,即使它被允许,代码仍然必须能够像没有删除副本一样工作。也就是说,必须有一个可访问的副本和/或移动构造函数。]
为什么即使允许发生复制省略,代码也有必要(在“保证复制省略”出现之前)维护复制/移动构造函数?
为什么“保证复制省略”将程序员从这些要求中解放出来?
当标准不保证(或要求)复制省略时,编译器就不需要实现它。
这意味着该标准允许编译器支持复制省略,但并不要求他们这样做。而且,在实践中,许多编译器供应商选择不实施复制省略。对于那些供应商来说,这是一个成本问题——不实现某个功能会消耗更少的开发人员工作量。对于程序员(使用编译器的人)来说,这是一个实现质量问题——与质量较低的编译器相比,更高质量的编译器更有可能实现所需的优化,包括复制省略——但获取成本也更高。
随着时间的推移,随着更高质量的编译器变得更加免费(根据“免费”的各种定义 - 并非所有都等同于零成本),该标准逐渐能够强制要求更多以前可选的功能。但它并不是这样开始的。
由于复制省略是可选的,一些编译器将依赖相关复制构造函数等的可访问性,而有些则不会。然而,符合标准要求的代码的概念,它使用一个兼容的编译器而不是另一个编译器构建,在标准中自然是不受欢迎的。因此,该标准要求构造函数是可访问的,即使在允许实现忽略它们的同时。
因为它只是被允许,但不能保证。
如果不需要可访问的复制构造函数,一些代码会在优化启动时编译,但在其他编译器上可能会失败。
为了保证代码能够工作,对于不能保证复制省略的每种情况,它必须有某种方式在没有复制省略的情况下工作。
为什么即使允许发生复制省略,代码也有必要(在“保证复制省略”出现之前)维护复制/移动构造函数?
因为正如其他人所说,只是允许省略复制或移动。并非每个编译器都必须省略它,因此为了保持一致性,程序员仍然安排复制/移动成为可能。从概念上讲,仍然存在复制/移动,是否由编译器执行是另一回事。
为什么“保证复制省略”将程序员从这些要求中解放出来?
因为一开始就没有复制或移动。保证复制“省略”通过完全改变 的含义来工作T a = T()
,即T()
初始化a
而不是临时对象,因此复制或移动构造函数在任何时候都不是游戏的一部分。