C++ 大括号的数量如何影响统一初始化?
考虑以下代码段:C++ 大括号的数量如何影响统一初始化?,c++,c++11,language-lawyer,uniform-initialization,list-initialization,C++,C++11,Language Lawyer,Uniform Initialization,List Initialization,考虑以下代码段: #include <iostream> struct A { A() {} A(const A&) {} }; struct B { B(const A&) {} }; void f(const A&) { std::cout << "A" << std::endl; } void f(const B&) { std::cout << "B" << std::endl;
#include <iostream>
struct A {
A() {}
A(const A&) {}
};
struct B {
B(const A&) {}
};
void f(const A&) { std::cout << "A" << std::endl; }
void f(const B&) { std::cout << "B" << std::endl; }
int main() {
A a;
f( {a} ); // A
f( {{a}} ); // ambiguous
f( {{{a}}} ); // B
f({{{{a}}}}); // no matching function
}
#包括
结构A{
A(){}
A(常数A&){}
};
结构B{
B(常数A&){}
};
void f(const A&{std::cout像这样很有趣
{a}
具有初始化常量a&
参数(临时)的精确匹配秩,这超过了用户定义的转换B(常量a&)
作为{a}
的实现。此规则是在C++14中添加的以解决列表初始化中的歧义(以及骨料的调整)
请注意,概念上的临时性是从未创建过的:在重载解析拾取
f(const A&)之后,引用很简单,这种解释甚至适用于不可复制的类型
a
或B
的构造函数初始化常量a&
参数(如上),因此调用不明确a(const a&)
),而不是允许每级重载解析进行一次这样的转换。因此,在第二种情况下,最外层的大括号必须将从{a}
初始化的a
初始化为(允许的)。(大括号的中间层可以初始化aB
,但是禁止将其与外层一起复制,并且没有其他方法可以尝试初始化。)不涉及大括号省略。我们不知道允许它的最外层目标类型。完全被吸引。但我认为您最好发布编译器消息。:@Constructor使用(至少)编译时,注释会给出错误消息g++,否则在执行过程中编写的内容可能需要在成员函数定义后添加标记
language labor
Nit:分号是毫无意义的,让未初始化的人想象所有的右括号都应该有一个。@Rakete1111:null语句比null声明(也不是语句)有更多的用途为了确保正确理解:<代码> f({a})< /代码>可以通过<代码> f(a {a})<代码>或<代码> f(b {a})< /代码>。因为第一个是完全匹配的,它是比第二个更好的匹配,并且调用是毫不含糊的。现在我们考虑第二种情况。<代码> f({{a}})< /代码>可以通过<代码> f(a {a{a}})<代码> >代码> f(b {a)。这第三个是完全匹配的,因此调用是不明确的。现在考虑第三个例子。<代码> f({{{a}}})< /代码>可以通过<代码> f(a {a{a}}})< <代码> >代码> f(b {a{a}}})<代码> >代码> f(b{b{a{a}}})< />代码>和<代码> f(b{b{b{a}}}){A} } /<代码>和<代码> f(b{b{a}})< /代码>。第一个是禁止的,第二个是。只有第三个是不被禁止的。我想我还没有理解它。如果问题是f(B{A{A}})
和f(B{B{A}})
是同样匹配的,那么当我们删除f(const A&)
时,调用仍然是不明确的。然而,编译器说的是相反的。@user1494080:不明确的地方是f(A{A}A}A})
(只有这两个转换中的外部是用户定义的)和f(B{A{A}})
f(B{B{A}})
是无效的,因为内部转换是用户定义的,因此外部转换不能是。请注意不对称性:{A}->A
是完全匹配的,但得到的{B{A}}->B
是用户定义的,因为必须进行重载解析才能识别{a}->B
转换。不f(a{a{a}})
调用两次一个相同的副本构造函数a(const a&)
?一个是用户定义的,另一个不是?@DavisHerring抱歉,我还在挣扎。f(B{B})
是禁止的,因为内部转换是用户定义的(我同意),外部转换也是用户定义的(这就是我对您的理解)不禁止,因为内部转换是完全匹配的,中间的转换是用户定义的,而外部的转换又是标准转换?为什么第一个f(B{B{…})
是用户定义的,第二个f(B{B{…})
不是?