c++ - 从大括号初始化列表直接初始化中的复制省略

标签 c++ language-lawyer copy-elision direct-initialization

在下面的程序中,对象 A a 直接从 braced-init-list {A{}} 初始化:

#include <iostream>

struct A {
    int v = 0;
    A() {}
    A(const A &) : v(1) {}
};

int main() {
    A a({A{}});
    std::cout << a.v;
}

MSVC 和 GCC 在这里打印 0 意味着复制省略发生了。并且 Clang 打印 1 执行复制构造函数。 在线演示:https://gcc.godbolt.org/z/1vqvf148z

哪个编译器就在这里?

最佳答案

Which compiler is right here?

我认为 clang 在使用复制构造函数和打印 1 方面是正确的,原因如下所述。

首先注意A a({A{}});直接初始化,从dcl.init#16.1可以看出:

  1. The initialization that occurs:

16.1) for an initializer that is a parenthesized expression-list or a braced-init-list,

16.2) for a new-initializer,

16.3) in a static_­cast expression ([expr.static.cast]),

现在,dcl.init#17.6适用于此处:

17.6) Otherwise, if the destination type is a (possibly cv-qualified) class type:

17.6.1) If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object. [ Example: T x = T(T(T())); calls the T default constructor to initialize x. — end example ]

17.6.2) Otherwise, if the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one is chosen through overload resolution ([over.match]). Then:

17.6.2.1) If overload resolution is successful, the selected constructor is called to initialize the object, with the initializer expression or expression-list as its argument(s).

(强调我的)

这意味着将使用/调用复制构造函数(这里是选定的构造函数)来初始化名为 a 的对象,并将表达式列表作为其参数,因为在您的复制构造函数的成员中initializer list 你正在将 a.v 初始化为 1,clang 的输出打印 1 是正确的。

关于c++ - 从大括号初始化列表直接初始化中的复制省略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73345030/

相关文章:

c++ - opengl中的路灯和阴影?

c++ - 如何配置 std::priority_queue 以忽略重复项?

c - 多个相同的原型(prototype)是否合法?

c++ - 为什么for_each通过move返回函数

c++ - 为什么在返回参数时不允许 RVO?

c++ - 两步复制省略以在构造函数调用中捕获右值作为实例变量

c++ - ATtiny85 数字 "on"输出无法提供 5 V

c++ - QT 多窗口信号/插槽阻止启动

c++ - C++ 中的条件表达式总是 bool 类型吗?

c++ - 在 C++17 中排序的移位操作数