【问题标题】:What is the difference, if any, between {x} and '= {x}' initialization?{x} 和 '= {x}' 初始化之间有什么区别(如果有的话)?
【发布时间】:2015-02-17 18:57:46
【问题描述】:

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

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

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

  1. x 的类型为 Foo
  2. Foo 有一个构造函数,它接受与 x 相同类型的参数。
  3. x 不是 Foo 类型,但可以使用转换构造函数。
  4. x 不是 Foo 类型,但可以使用 explicit 转换构造函数。

我的意思是,在每种情况下:

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

【问题讨论】:

标签: c++ c++11


【解决方案1】:
Foo foo{x};    // 1

Foo foo = {x}; // 2

1 是直接列表初始化。 2 是复制列表初始化

假设Foo 是一个类类型,那么在大多数情况下,无论在概念上还是其他方面,它们都会做同样的事情,除非在重载决策期间选择了显式构造函数,那么#2 是非良构的。特别是,与复制初始化不同,复制列表初始化在概念上并不构造一个临时的。

一个例外是xFoo 类型或从其派生的类型。在这种情况下,#1 等价于Foo foo(x);(即,direct-initialization),而#2 等价于Foo foo = x;(即,copy-initialization)。细微的区别是,在这种情况下,#2 的重载决议只考虑非显式构造函数,而不是考虑所有构造函数,然后在选择显式构造函数时变得格式错误。* 此异常由 CWG issue 1467 的决议添加, 于去年 11 月通过。


* 你必须编写一些相当折磨人的代码才能做到这一点。例如:

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

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

CWG1467 之前的第 1 行格式错误,因为重载决议选择了X(X&),即explicit。在 CWG1467 之后,不考虑 explicit 构造函数 X(X&),因此使用 X(const X&)。请注意,第 2 行总是格式正确并使用X(const X&)

【讨论】:

  • 您可能想通过引用标准中的相关部分来改进这个答案,澄清一些部分等等。
  • @black IMO 引用标准来解释初始化会导致臃肿,除非这是一个语言律师式的问题。 OP本质上是在询问初始化是如何工作的,这是不必要的。
  • @remyabel 嗯,是的,但我认为答案应该扩大到更完整地涵盖 OP 询问的主题。
  • @black 如果您阅读了这个问题,您可以看到 OP 询问了 4 个不同的案例,每个案例有 3 个问题。我不明白为什么 T.C.当他到目前为止所拥有的足够多的时候,他应该不得不跳过铁环来做出不必要的臃肿答案。
  • @remyabel 不同的 POV。现在答案已经更新,它似乎更有效。 --结束加时。]
猜你喜欢
  • 1970-01-01
  • 2023-03-27
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多