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

问题描述

从标准6.7.7(临时对象)可以看出:

当类类型 X 的对象被传递给函数或从函数返回时,如果 X 至少有一个符合条件的复制或移动构造函数([特殊]),则每个这样的构造函数都是平凡的,而 X 的析构函数要么是平凡的或删除,允许实现创建一个临时对象来保存函数参数或结果对象。临时对象分别由函数参数或返回值构造,函数的参数或返回对象被初始化,就像使用合格的平凡构造函数复制临时对象一样(即使该构造函数不可访问或不会被重载选择)执行对象的复制或移动的分辨率)。 [注 4:允许将类类型的对象传递给寄存器中的函数或从函数返回该范围。 — 尾注]

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

解决方法

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

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

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

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

——否则,如果目标类型是一个(可能是 cv 限定)类类型:

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