列表初始化的复制省略,它在标准中的何处规定?
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已经解决了这个缺陷。
在[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已经解决了这个缺陷。