- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在 C++11 中,我们可以使用“brace-or-equal-initializer”(标准中的词)进行类内初始化,如下所示:
struct Foo
{
/*explicit*/ Foo(int) {}
};
struct Bar
{
Foo foo = { 42 };
};
但是如果我们取消注释 explicit
,它就不再编译了。 GCC 4.7 和 4.9 是这样说的:
error: converting to ‘Foo’ from initializer list would use explicit constructor ‘Foo::Foo(int)’
我觉得这很令人惊讶。这段代码不编译真的是C++11标准的本意吗?
删除 =
修复它:Foo foo { 42 };
但我个人觉得这很难向习惯于使用 表单的人解释=
几十年了,由于标准提到了“大括号或等号初始化器”,因此旧的好方法在这种情况下不起作用并不明显。
最佳答案
我无法解释这背后的基本原理,但我可以重复显而易见的事情。
I found this surprising. Is it really the intention of the C++11 standard that this code doesn't compile?
§13.3.1.7
In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.
Removing the = fixes it:
Foo foo { 42 };
but I personally find this harder to explain to people who have been used to the form with = for decades, and since the standard refers to a "brace-or-equal-initializer" it's not obvious why the good old way doesn't work in this scenario.
Foo foo { 42 }
是 direct initialization , 而等号(带大括号)使它成为 copy-list-initialization .另一个答案的原因是因为 copy-initialization 的编译失败(不带大括号的等号),那么它也因复制列表初始化而失败也就不足为奇了,但这两个失败的原因不同。
cppreference:
Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and user-defined conversion functions, while direct-initialization considers all constructors and implicit conversion sequences.
还有他们在 explicit specifier 上的页面:
Specifies constructors and (since C++11) conversion operators that don't allow implicit conversions or copy-initialization.
另一方面,对于复制列表初始化:
T object = {arg1, arg2, ...}; (10)
10) on the right-hand-side of the equals sign (similar to copy-initialization)
Otherwise, the constructors of T are considered, in two phases:
- If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all)
如 What could go wrong if copy-list-initialization allowed explicit constructors? 中所述,编译失败,因为选择了显式构造函数但不允许使用。
关于C++11: "= {}"的类内初始化不适用于显式构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26137325/
我是一名优秀的程序员,十分优秀!