首页 > 解决方案 > 声明 POD 结构而不使用默认构造函数时会实例化什么?

问题描述

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

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

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

struct C
{
    int x; 
    int y;
};

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

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).

那很有意思。我之前使用过 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 类型的对象意味着:

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

标签: c++

解决方案


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

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

不。

您的第一个链接答案对 C++11 起是正确的,这称为默认初始化。它不同于默认构造或值初始化。

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

默认初始化的效果是:

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

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

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


N4659 的本地副本与上面的摘要一致:

11.6 初始化器 [dcl.init]

...

(7.3) 否则不进行初始化

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

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


目前的草案有

9.3初始化器 [dcl.init]

...

(7.3)否则,不执行初始化。


推荐阅读