Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 大括号的数量如何影响统一初始化?_C++_C++11_Language Lawyer_Uniform Initialization_List Initialization - Fatal编程技术网

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
    初始化为(允许的)。(大括号的中间层可以初始化a
    B
    ,但是禁止将其与外层一起复制,并且没有其他方法可以尝试初始化。)
  • 每一种解释都涉及这样一种不允许的额外转换

  • 不涉及大括号省略。我们不知道允许它的最外层目标类型。

    完全被吸引。但我认为您最好发布编译器消息。:@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{…})
    不是?