有一段关于 C++ 草稿 n4606 [dcl.init] 17.6中保证复制省略的段落:
- 如果目标类型是( 可能是 cv ) 类类型:
- 如果初始值设定项表达式为 prvalue,源类型的版本与目标类的类相同,则初始化器表达式初始化。 [ 示例:
T x = T(T(T()));
调用T
默认构造函数以初始化x
。 — 结束示例 ] - [... ]
- 如果初始值设定项表达式为 prvalue,源类型的版本与目标类的类相同,则初始化器表达式初始化。 [ 示例:
还有一个 q&插件,讨论它是如何工作的。
我引用了,当初始值设定项表达式为prvalue且源类型的类与目标类别相同时,则引用了 ctors 。 因此无需检查复制或者移动表达式的存在,这使得以下代码在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
但是,我疯狂的是,我在 C++ 草案n4606中的列表初始化部分找不到类似的规则。 我发现的是( [dcl.init.list] 3.6 )
[... ]
- 否则,如果
T
是类类型,则将构造函数视为。 列举了适用的构造函数,通过重载解析( 13.3,13.3.1.7 ) 选择最佳的构造函数。 如果需要收缩转换( 请参见下面) 来转换任何参数,则程序的格式不正确。 [... ]
由于列表初始化比我引用的第一个规则高,因这里初始化初始化时应考虑列表初始化的规则。 可以看到,构造函数在列表初始化类类型 T
时被考虑。 因此,继续前一个示例,将
A ff() { return {A()}; }
在C++17中合法有人可以找到标准草稿指定如何确保在列表初始化中保证省略省略。