C++ 为什么即使允许发生复制省略,代码也需要有一个可访问的复制/移动构造函数?

C++ 为什么即使允许发生复制省略,代码也需要有一个可访问的复制/移动构造函数?,c++,c++14,language-lawyer,copy-elision,C++,C++14,Language Lawyer,Copy Elision,Nicol Bolas在SO中写道: 在许多情况下都允许发生拷贝省略。 然而,即使允许,代码仍然必须能够 工作时就好像副本没有被删掉一样。也就是说,必须有一个 可访问的复制和/或移动构造函数。] 为什么(在“保证拷贝省略”出现之前)代码有必要维护拷贝/移动构造函数,即使拷贝省略被允许发生 为什么“”使程序员免于这些要求 为了保证代码能够工作,它必须有一些方法在不保证复制省略的情况下工作。因为它只是被允许的,但没有保证 如果不需要可访问的复制构造函数,则某些代码会在优化开始时编译,但可能会在其他编

Nicol Bolas在SO中写道:

在许多情况下都允许发生拷贝省略。 然而,即使允许,代码仍然必须能够 工作时就好像副本没有被删掉一样。也就是说,必须有一个 可访问的复制和/或移动构造函数。]

为什么(在“保证拷贝省略”出现之前)代码有必要维护拷贝/移动构造函数,即使拷贝省略被允许发生


为什么“”使程序员免于这些要求

为了保证代码能够工作,它必须有一些方法在不保证复制省略的情况下工作。

因为它只是被允许的,但没有保证


如果不需要可访问的复制构造函数,则某些代码会在优化开始时编译,但可能会在其他编译器上失败。

如果标准没有保证(或要求)复制省略,则不要求编译器实现它

这意味着标准允许编译器支持拷贝省略,但不要求编译器支持拷贝省略。而且,在实践中,许多编译器供应商选择不实现复制省略。对于那些供应商来说,这是一个成本问题——不实现一个特性会消耗更少的开发人员的精力。对于程序员(使用编译器的人)来说,这是一个实现质量问题——与低质量的编译器相比,高质量的编译器更有可能实现理想的优化,包括复制省略——但获取成本也更高

随着时间的推移,随着更高质量的编译器变得更加免费(根据“免费”的各种定义,并非所有编译器都等同于零成本),标准逐渐能够强制要求提供更多以前可选的功能。但事情并不是这样开始的

由于拷贝省略是可选的,一些编译器将依赖于相关拷贝构造函数等的可访问性,而有些编译器则不会。然而,符合标准要求的代码的概念,即使用一个兼容的编译器而不是另一个编译器构建的代码,在标准中自然是不可取的。因此,该标准要求构造函数必须是可访问的,即使在允许实现省略它们的情况下也是如此

为什么(在“保证拷贝省略”出现之前)代码有必要维护拷贝/移动构造函数,即使拷贝省略被允许发生

因为正如其他人所说,只是允许省略复制或移动。并不是每个编译器都必须省略它,因此为了保持一致性,程序员仍然安排复制/移动成为可能。从概念上讲,仍然存在复制/移动,不管它是否由编译器执行,都是另一回事

为什么“保证拷贝省略”使程序员免于这些要求


因为一开始就没有复制或移动。保证复制“省略”的工作原理是完全改变
ta=T()
的含义,即
T()
初始化
a
而不是临时对象,因此在任何时候复制或移动构造函数都不是游戏的一部分。

为什么其他编译器不执行复制省略,什么时候允许发生?可以,但不是必须的。也许在某些情况下很难做到?不管怎样,规则是允许编译器以任何方式工作的。@ CukuBubILL C++标准委员会对他们决定执行什么是非常谨慎的。可能有一些不可预见的情况,在这些情况下,复制省略将是一种悲观,因此他们将选择权留给了编译器。在C++17中,凭借额外的经验,他们认为发生这种情况的可能性可以忽略不计,因此在适用的情况下,现在可以保证省略副本。@Boperson Richard Smith说:
本文描述的方法不是通过省略副本,而是通过重新定义值类别来实现这一点(glvalue与prvalue)这样一来,首先执行复制是不自然的。
我很难理解“硬”是如何实现的对于这样一个编译器,只需更改标准中某些值类别的定义,部分就会消失。@WakeupBrazil好吧,如果在prvalue之前不存在的东西现在是prvalue,那么你知道你可以窃取它,因为它是prvalue。另外,一些不是xvalue但现在是xvalue的东西也可以安全地删除。这都是ab我们表达了意图,新规则赋予了编译器这种意图。在它必须做一些静态分析来弄清楚它之前。至少这是我对它的看法。让代码被一些编译器接受,而不是其他编译器接受,应该被认为比让代码被所有编译器接受,但有不同的含义要令人反感得多一组任务,这些任务可以由可能被某些(甚至大多数)拒绝的程序完成实现,但不会在任何接受它们的实现上调用UB,这将远远大于在所有实现上可以成功执行的任务集。IMHO,标准应该为此类程序定义一个类别,并寻求最大化它们可以执行的任务数。也许是这样,supercat。但我的答案是关于标准要求背后的逻辑(即,使用一个符合标准的实现编译的代码不应无法使用另一个符合标准的实现编译).如果您认为前提需要改变,请与标准化委员会联系-他们同意这样做,而不是我。如果不使用99%但不是100%的平台都可以支持的功能,许多任务就无法高效执行。早期的标准化委员会并不是试图定义语言的所有方面为了容纳