{x}和'= {x}'初始化之间有什么区别?

时间:2015-02-17 18:57:47

标签: c++ c++11

我试图理解这两种初始化方式之间的语义差异:

Foo foo{x};
Foo foo = {x};

我很想知道以下情况的区别:

  1. x的类型为Foo
  2. Foo有一个构造函数,它接受与x。
  3. 相同类型的参数
  4. x不属于Foo类型,但可以使用转换构造函数。
  5. x不属于Foo类型,但可以使用explicit转换构造函数。
  6. 根据差异我的意思是,在每种情况下:

    1. 从概念上讲,调用了哪些构造函数?
    2. 编译器通常会优化哪些构造函数调用?
    3. 是否允许隐式转换?

1 个答案:

答案 0 :(得分:20)

Foo foo{x};    // 1

Foo foo = {x}; // 2

1是 direct-list-initialization 。 2是 copy-list-initialization

假设Foo是类类型,那么在大多数情况下,它们在概念上或其他方面完全相同,除非在重载解析期间选择了显式构造函数,那么#2是不正确的。特别是,与复制初始化不同,复制列表初始化在概念上不构造临时。

一个例外是x属于Foo类型或从中派生的类型。在这种情况下,#1相当于Foo foo(x);(即直接初始化),而#2相当于Foo foo = x;(即复制初始化)。细微差别在于,在这种情况下,#2的重载解析只考虑非显式构造函数,而不是考虑所有构造函数,如果选择了显式构造函数则会变得格式不正确。*此异常由{{3的分辨率添加这是去年十一月通过的。


*你必须为此写一些非常折磨的代码。例如:

struct X
{
    X() = default;
    explicit X(X&);
    X(const X&);
};

int main() { 
    X x1;
    X x2 = {x1}; // #1
    X x3 = x1;   // #2
}

Pre-CWG1467,第1行格式不正确,因为重载决策选择X(X&),即explicit。在CWG1467之后,explicit构造函数X(X&)未被考虑,因此使用了X(const X&)。请注意,第2行始终格式正确,并使用X(const X&)