【问题标题】:What is instantiated when a POD structure is declared without using a default constructor?声明 POD 结构而不使用默认构造函数时会实例化什么?
【发布时间】:2019-12-20 08:21:35
【问题描述】:

当我们的团队处理关于 C++ 代码中 POD 的单元化成员的 valgrind 警告时,我得到了这个有趣的答案:

https://stackoverflow.com/a/5914697/629530

重申要点,考虑以下 C++ 中的 POD 结构:

struct C
{
    int x; 
    int y;
};

以下构造 C 类型对象的调用会调用默认构造函数,并使用该默认构造函数初始化成员(同样,从 Martin York 的答案中复制代码和 cmets):

C  c = C();      // Zero initialize using default constructor
C  c{};          // Latest versions accept this syntax.
C* c = new C();  // Zero initialize a dynamically allocated object.

有道理。 Martin York 继续指出,在以下声明中,c 的成员不是通过构造函数初始化的,因此包含未定义的数据:

C  c;            // members are random
C* c = new C;    // members are random (more officially undefined).

这很有趣。我之前使用过 braced-init-list 初始化 POD 类型,但我没有意识到 C c; 不会调用 POD 类型的默认构造函数。他的回答满足了这个问题,但我想知道在声明后者的非默认构造的 c 对象时具体实例化了什么。具体来说,以下内容对我有帮助:

  1. 这种 POD 类型的非默认初始化的正式名称是什么?由于我不知道它的名称,我无法在谷歌上搜索该机制。
  2. 如果 POD 类型有一些比 int 类型更重要的东西,例如 std::string,那么该成员的内存是否也用未定义的值初始化?或者是为该成员调用的 std::string 的默认构造函数?

更新。

感谢您的意见。这已被复制到一个带有这个单一答案的问题: https://stackoverflow.com/a/8860787/629530

根据该答案(以及它所复制到的问题的答案),不带括号的表单声明称为“默认初始化”:

Info *p = new Info;      <------- Default Initialization

对于默认初始化,关于初始化的几点说明:

默认初始化 T 类型的对象意味着:

  • 如果 T 是非 POD 类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化格式错误);
  • 如果 T 是数组类型,则每个元素都是默认初始化的;
  • 否则,对象被零初始化。

我可能误解了一些东西,但上面提出的名为 C 的结构是 POD 类型,而不是数组。因此它应该是零初始化的?然而,成员不是零初始化的,而是包含未定义的值。我该如何调和呢?

【问题讨论】:

  • 问题 1. 您是否正在寻找value initialization?问题 2 应该单独提出,没有这么多的序言(并立即作为副本的副本关闭)

标签: c++


【解决方案1】:

默认初始化 T 类型的对象意味着:

...否则,对象被零初始化。

没有。

您的first linked answer 是正确的关于 C++11 及以上版本,这称为默认初始化。它不同于默认构造或值初始化。

second linked answer 对于 C++03 可能是正确的,但对于 C++11 以后的版本是错误的(即使它是在 2012 年编写的)。我没有要验证的 '03 标准副本,而且是很久以前的事了。

default initialization的作用是:

  • 如果 T 是非 POD(C++11 前)类类型,则考虑构造函数并对其进行针对空参数列表的重载决议。调用选择的构造函数(默认构造函数之一)为新对象提供初始值;

  • 如果 T 是数组类型,则数组的每个元素都是默认初始化的;

  • 否则,什么都不做:具有自动存储持续时间的对象(及其子对象)被初始化为不确定的值。


N4659 的本地副本与上面的总结一致:

11.6 初始化程序 [dcl.init]

...

(7.3) 否则不进行初始化

关于new-expressions的部分甚至提到了11.6然后说

注意:如果不执行初始化,则对象具有不确定的值。——结束注释


当前草稿有

9.3 初始化器 [dcl.init]

...

(7.3)否则不进行初始化。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 2019-07-07
相关资源
最近更新 更多