复制省略和简单可复制类型

Copy elision and trivially copyable types

提问人:Antoine Morrier 提问时间:5/4/2021 最后编辑:Antoine Morrier 更新时间:5/5/2021 访问量:325

问:

从标准的 6.7.7(临时对象)中,我们可以看到:

当类类型 X 的对象传递给函数或从函数返回时,如果 X 至少有一个合格的复制或移动构造函数 ([special]),则每个此类构造函数都是微不足道的,并且 X 的析构函数是微不足道的或已删除的,则允许实现创建一个临时对象来保存函数参数或结果对象。临时对象分别由函数参数或返回值构造,并且函数的参数或返回对象被初始化,就像使用符合条件的普通构造函数复制临时构造函数一样(即使该构造函数不可访问或不会通过重载解析选择来执行对象的复制或移动)。 [注4:授予此自由度是为了允许类类型的对象传递给寄存器中的函数或从寄存器中的函数返回。

这是否意味着对于简单可复制的类型,复制省略不是强制性的?我在这里的理解是,如果我们声明一个析构函数,而不是不声明任何东西(因此析构函数将由编译器生成)或默认的析构函数,则该对象变得不容易构造,因此,必须执行复制省略(在我们尊重众所周知的复制省略条件的条件下)。~Object() {}

C++ 17 C++ 20 复制省略

评论

1赞 Peter 5/4/2021
你需要更精确地标记问题,以及你所指的 C++ 标准的哪个版本(或草案)。标记“C++17”意味着 2017 年标准,而该标准根本没有第 6.7.7 节(更不用说带有临时对象标题的章节了)。
1赞 StoryTeller - Unslander Monica 5/4/2021
但它确实有 [class.temporary],它在 C++20 中是 6.7.7,在 C++17 中是 15.2。这就是为什么,OP,您应该更喜欢稳定的截面指示符。

答:

4赞 rustyx 5/4/2021 #1

这是否意味着对于简单可复制的类型,复制省略不是强制性的?

原则上,是的,但你引用的部分的目标不是免除 POD 类型的复制省略,而是绕过 ABI 对如何在函数调用中传递对象的限制。它允许 POD 对象通过寄存器传递。这是标准能做的最好的事情,因为 C++ 抽象机器对物理机器及其寄存器和调用约定一无所知。

保证复制省略是贯穿整个标准的几项更改的结果,其中包括延迟的 prvalue 实现。有关详细信息,请参阅原始提案 p0135r1

通过这些更改,可以(并且需要)在不涉及临时对象的情况下初始化对象 ([dcl.init.general]/15.6.1):

— 否则,如果目标类型是 (可能 CV-Qualified) 类类型:

  • 如果初始值设定项表达式是 prvalue,并且源类型的 cv 非限定版本与 类,初始值设定项表达式用于 初始化目标对象。