列表初始化的复制省略,它在标准中的何处规定?

Copy elision for list-initialization, where is it stated in the standard?

[dcl.init]/17.6中明确写到,对于括号初始化的情况,会出现copy elision:

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 ]

但是在列表初始化的情况下,上面的段落不适用,我没有发现任何类似的东西。参见 [dcl.init.list]

那么为什么在这种情况下存在复制省略:T x{T(T())}; 根据 C++17 标准。

根据目前的草案,这种情况下没有复制省略。

考虑以下示例:

#include <iostream>
#include <initializer_list>

struct S {
    S() {std::cout << "default\n";}
    S(const S&) {std::cout << "copy\n";}
    S(std::initializer_list<S>) {std::cout << "initializer list\n";}
};

int main()
{
    S s = S{S()};
}

根据Core Language Issue 2137, the constructor taking std::initializer_list as parameter should be chosen (Clang may choose copy constructor or perform copy elision here, which )。因此,此类列表初始化应考虑构造函数。

The problem is that when copy/move constructor is selected, it is reasonable to elide this copy/move.事实上,Core Language Issue 2327已经解决了这个缺陷。