c++11 - 为什么 `vector<int> v{{5,6}};` 有效?我以为只允许一对 {}?

标签 c++11 initializer-list

给定一个类A有两个构造函数,取 initializer_list<int>initializer_list<initializer_list<int>>分别,那么

A v{5,6};

调用前者,并且
A v{{5,6}};

正如预期的那样调用后者。 (clang3.3,显然 gcc 的行为不同,请参阅答案。标准要求什么?)

但是如果我删除第二个构造函数,那么 A v{{5,6}};仍然编译,它使用第一个构造函数。我没想到会这样。
我以为 A v{5,6}将是访问 initializer_list<int> 的唯一方法构造函数。

(我在玩 std::vectorthis question I asked on Reddit 时发现了这一点,但我创建了自己的 A 类以确保它不仅仅是 std::vector 接口(interface)的怪癖。)

最佳答案

我认为这是 answer might be relevant .

Yes, this behaviour is intended, according to §13.3.1.7 Initialization by list-initialization

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.

— If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.



gcc我试过你的例子。我收到此错误:
error: call of overloaded 'A(<brace-enclosed initializer list>)' is ambiguous
gcc如果我使用三套支架,就不再提示了。 IE。:

#include <iostream>
#include <vector>
#include <initializer_list>

struct A {
    A (std::initializer_list<int> il) { 
        std::cout << "First." << std::endl;
    }
    A (std::initializer_list<std::initializer_list<int>> il) { 
        std::cout << "Second." << std::endl;
    }
};

int main()
{
    A a{0}; // first
    A a{{0}}; // compile error
    A a2{{{0}}}; // second
    A a3{{{{0}}}}; // second
}

为了反射(reflect)向量的构造函数,这是我的结果:
#include <iostream>
#include <vector>
#include <initializer_list>

struct A {
    A (std::initializer_list<int> il) { 
        std::cout << "First." << std::endl;
    }
    explicit A (std::size_t n) {
        std::cout << "Second." << std::endl;
    }
    A (std::size_t n, const int& val) {
        std::cout << "Third." << std::endl;
    }
    A (const A& x) {
        std::cout << "Fourth." << std::endl;
    }
};

int main()
{
    A a{0};
    A a2{{0}};
    A a3{1,2,3,4};
    A a4{{1,2,3,4}};
    A a5({1,2,3,4});
    A a6(0);
    A a7(0, 1);
    A a8{0, 1};
}

main.cpp:23:10: warning: braces around scalar initializer

    A a2{{0}};

         ^~~

1 warning generated.

First.
First.
First.
First.
First.
Second.
Third.
First.

关于c++11 - 为什么 `vector<int> v{{5,6}};` 有效?我以为只允许一对 {}?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20714273/

相关文章:

c++ - 初始化顺序和移动语义

c++ - 保持 std::mutex 锁定/解锁公开的基本原理

templates - C++11 中迭代器的类型别名/using 声明

c++ - 将类的成员函数传递给 std::thread

c++ - 什么时候为类成员释放使用 alloca 分配的内存?

c++ - C++中的初始化列表名称冲突

C++ 初始化指针/引用/复制的细微差别

c++ - 将参数传递给 "array-like"容器构造函数

c++ - 带有指向可变模板模板参数的指针的类

c++ - 在构造函数初始化器中初始化成员数组