C++11:列表初始化中的 () 或 {}?

C++11: () or {} in List-initialization?

我指的是“The working draft N3337", which is said most similar to the published C++11 standard

如果有匹配的构造函数,则调用构造函数。

Example (p200):
struct S {
    // no initializer-list constructors
    S(int, double, double); // #1
    S(); // #2
    // ...
};

S s1 = { 1, 2, 3.0 }; // OK: invoke #1
S s2 { 1.0, 2, 3 }; // error: narrowing

否则,将使用聚合初始化。

现在,here 是一个使用 vector 的示例,它有一个来自 size_t 的显式构造函数和一个 initializer_list 构造函数:

vector<double> v1(7);   // ok: v1 has 7 elements
vector<double> v1{7};   // ok: v1 has 1 element (with its value 7.0)

在这里我很困惑。为什么 vector 构造函数的行为与 S 构造函数的行为不同?

因为 initializer_list 重载强烈优于所有其他重载。来自 [over.match.list]:

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

(1.1) — 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.
(1.2) — 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.

vector 是一个非聚合 [​​=26=],它有两个相关的构造函数:

explicit vector( size_type count );           // (3)
vector( std::initializer_list<T> init,        // (7)
    const Allocator& alloc = Allocator() );

根据 [over.match.best] 中描述的顺序,由于 (7) 是一个可行的构造函数候选者,我们不会指出 (1.2) 其中 (3) 会被考虑。