【问题标题】:Copy elision and trivially copyable types复制省略和普通可复制类型
【发布时间】:2021-05-04 08:48:48
【问题描述】:

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

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

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

【问题讨论】:

  • 您需要更准确地标记问题的方式,以及您所指的 C++ 标准的哪个版本(或草案)。标记“C++17”意味着 2017 年标准,并且该标准根本没有第 6.7.7 节(更不用说带有关于临时对象的标题)。
  • 但它确实有 [class.temporary] 在 C++20 中为 6.7.7,在 C++17 中为 15.2。这就是为什么,OP,你应该更喜欢 stable 部分指示符。

标签: c++ c++17 c++20 copy-elision


【解决方案1】:

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

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

保证复制省略是在整个标准中传播的若干更改的结果,其中包括延迟纯右值实现。详情参考原提案p0135r1

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    相关资源
    最近更新 更多