【问题标题】:List initialization - What changed in C++14?列表初始化 - C++14 中发生了什么变化?
【发布时间】:2020-06-28 23:11:33
【问题描述】:

这两行来自cppreference

这两种说法有什么区别?我看不出有什么区别

直到 c++14

如果括号初始化列表为空并且 T 是一个具有默认值的类类型 构造函数,执行值初始化。否则,如果 T 是 聚合类型,进行聚合初始化。

c++14 起

如果 T 是聚合类型,则执行聚合初始化。 否则,如果括号初始化列表为空并且 T 是一个类类型 默认构造函数,执行值初始化。

【问题讨论】:

  • 感谢 @cigien@StoryTeller 的编辑。

标签: c++ language-lawyer list-initialization


【解决方案1】:

不同之处在于当两个条件都适用时会发生哪一个:如果 T 是一个聚合类(而不是一个数组),它肯定有一个默认构造函数, braced-init-list 是空的。当然,要理解为什么这很重要,我们必须将值初始化与聚合初始化与空列表区分开来。

值初始化对对象进行零初始化,然后对其进行默认初始化,对于聚合而言,默认初始化其每个成员,因此值初始化是按成员进行的(加上零填充)。聚合初始化从{} 中初始化每个成员,这又是许多类型的值初始化,但对于具有用户提供的默认构造函数的类类型的成员是默认初始化。区别可见

struct A {A() {} int i;};
struct B {A a;};  // aggregate
B b{};     // i is 0 in C++11, uninitialized in C++14
B b2=B();  // i is 0 in both versions

仅在 C++14 中,聚合可以有默认的成员初始化器;当然,这不会导致两种语言版本之间的行为差​​异,但是无论如何它在这两种规则之间的行为并没有不同(因为它只替换了常见的默认初始化)。

【讨论】:

  • 并非所有聚合都有未删除的默认构造函数(例如,struct X {const int x; };)。
  • @T.C.:是的,但是这里不考虑构造函数是否被删除(当然初始化可能是错误的)。或者这就是你的意思,用{} 初始化这样的类型在 C++11 中是不正确的,但在 C++14 中不是?
  • 在 N3337 中,格式良好的 depends on whether X's deleted default constructor is trivial - 我认为是 under the definition at the time。如果我正确阅读了 wiki 注释,CWG1301 更改了值初始化的定义以拒绝已删除的构造函数,并重新排序项目符号以保留 {} 的有效性。
【解决方案2】:

不同之处在于检查的顺序,因此首先进行聚合类型检查,然后才是其余的。

【讨论】:

  • 而这个变化有什么影响?
猜你喜欢
  • 2022-12-02
  • 2013-05-13
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多