复制省略和可平凡复制类型

3
从标准6.7.7(临时对象)中,我们可以看到:
当将类类型X的对象传递给函数或从函数返回时,如果X具有至少一个合格的复制或移动构造函数([特殊]),每个这样的构造函数都是平凡的,并且X的析构函数要么是平凡的,要么被删除,实现允许创建一个临时对象来保存函数参数或结果对象。分别从函数参数或返回值构造临时对象,并使用合格的平凡构造函数将函数的参数或返回对象初始化为复制临时对象(即使该构造函数不可访问或不会被重载决议选择来执行对象的复制或移动)。 [注4:授予这种自由度是为了允许将类类型的对象传递给函数或从函数返回寄存器。—结束语]
这是否意味着在平凡可复制类型中不强制执行复制省略?我理解的是,如果我们声明像 ~Object() {} 这样的析构函数而不是不声明任何内容(因此编译器将生成析构函数)或默认析构函数,则对象变得不可平凡构造,因此必须执行复制省略(在满足复制省略发生的众所周知条件的情况下)。

1
你需要在标记问题时更加精确,并指明你所引用的C++标准的发布版本(或草案)。使用"C++17"作为标记意味着2017年的标准,并且那个标准根本没有6.7.7节(更不用说有关临时对象的标题了)。 - Peter
1
但它确实有**[class.temporary]*,在C++20中为6.7.7,在C++17中为15.2。这就是为什么,楼主,你应该更喜欢稳定*的部分标识符。 - StoryTeller - Unslander Monica
1个回答

4
这是否意味着对于平凡可复制类型(copy elision)不是强制的? 原则上是的,但你引用的这一部分的目标不是豁免POD类型(Pod types)的拷贝省略(copy elision),而是绕过关于对象在函数调用中如何传递的ABI限制。它允许通过寄存器传递POD对象。这是标准能做到的最好的事情,因为C++抽象机不知道物理机器及其寄存器和调用约定(call conventions)的任何信息。
保证拷贝省略是标准中分散于多处的几个更改的结果,其中包括延迟PRValue的材料化(Deferred prvalue materialization)。有关详细信息,请参阅原始提议 p0135r1。
有了这些变化,就可以初始化一个对象而不涉及临时变量(temporaries)(dcl.init.general/15.6.1):
- 否则,如果目标类型是一个(可能带cv限定符的)类类型: - 如果初始化表达式是一个prvalue,并且源类型的cv无限定版本与目标类相同,则使用初始化表达式来初始化目标对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接