在c ++草案n4606 [dcl.init] 17.6中有一段关于保证副本省略的段落:
- 如果目标类型是(可能是cv限定的)类类型:
- 如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象.[ 示例:
T x = T(T(T()));调用T默认构造函数进行初始化x.- 结束例子 ]- [...]
还有关于它如何运作的问答报告.
对我自己的理解,我引用的规则保证当初始化表达式是prvalue并且源类型的cv-nonqualified版本与目标类相同时,不应该涉及ctors.所以不需要检查复制的存在或移动ctor,这使得下面的代码在C++ 17中是合法的:
struct A {
A() {}
A(A const &) = delete;
A(A &&) = delete;
};
A f() { return A(); } // it's illegal in C++14, and suppose to be legal in C++17
Run Code Online (Sandbox Code Playgroud)
然而,令我发疯的是我在c ++ draft n4606的list-initialization部分找不到类似的规则.我发现的是([dcl.init.list] 3.6)
[...]
- 否则,如果
T是类类型,则考虑构造函数.枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数.如果转换任何参数需要缩小转换(见下文),则程序格式错误.[...]
由于列表初始化的优先级高于我引用的第一个规则,因此当初始化程序是初始化程序列表时,我们应该考虑列表初始化部分中的规则.我们可以看到,在列表初始化类类型时会考虑构造函数T.所以,继续前面的例子,将
A ff() { return {A()}; }
Run Code Online (Sandbox Code Playgroud)
在C++ 17中合法吗?有人可以找到标准草案指定保证副本省略在列表初始化中如何工作的地方吗?