【问题标题】:Default initialization of POD vs. non-POD class typesPOD 与非 POD 类类型的默认初始化
【发布时间】:2011-11-24 11:26:47
【问题描述】:

C++ 标准说 (8.5/5):

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

  • 如果 T 是非 POD 类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有 可访问的默认构造函数)。

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

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

使用此代码

struct Int { int i; };

int main()
{
    Int a;
}

对象 a 是默认初始化的,但显然 a.i 不一定等于 0 。这不与标准相矛盾吗,因为Int 是 POD 而不是数组?

编辑class 更改为struct,因此Int 是一个POD。

【问题讨论】:

  • "显然 a.i 不一定等于 0" 为什么? “否则,对象被零初始化。”。
  • 您正在阅读过时的规范。在最新的规范中,默认初始化将使您的值未初始化
  • @JohannesSchaub-litb 你能显示更新后的文字吗?

标签: c++ initialization c++03


【解决方案1】:

从 2003 年标准的 8.5.9 开始:

如果没有为对象指定初始化器,并且该对象属于 (可能是 cv 限定的)非 POD 类类型(或其数组), 对象应默认初始化;如果对象是 const 限定类型,基础类类型应具有 用户声明的默认构造函数。 否则,如果没有初始化器 为非静态对象、对象及其子对象指定,如果 任何,具有不确定的初始值);如果对象或任何 它的子对象是 const 限定类型,程序格式错误。

您显示的类是 POD,因此突出显示的部分适用,并且您的对象根本不会被初始化(因此您引用的第 8.5/5 节根本不适用)。

编辑:根据您的评论,此处引用当前标准最终工作草案的第 8.5/5 节(我没有真正的标准,但 FDIS 据说非常关闭):

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

——如果 T 是一个(可能 cv-qualified) 类类型(第 9 条),T 的默认构造函数是 调用(如果 T 没有可访问的,则初始化格式错误 默认构造函数);

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

否则,不执行初始化。

【讨论】:

  • 根据标准,一个POD的所有非静态数据成员必须具有相同的访问控制;它不需要是public
  • @Gorpik:可能在 C++11 中发生了变化,但在 C++03 中,POD 是一个聚合,聚合不能有任何私有或受保护的非静态数据成员(8.5 .1.1).
  • @Björn 我没有标准。我在我的问题中复制的部分是从 SO 中的其他问题中获得的。您的答案如何与我上面显示的标准部分联系起来?
  • @user1042389:您引用的部分仅在您使用默认初始化时适用。我引用的部分指定您显示的示例不执行任何初始化,因此您引用的部分不适用。
  • @Björn 根据stackoverflow.com/q/1613383/1042389,我的示例是默认初始化。还能是什么?
【解决方案2】:

您的变量未初始化。 使用

Int a = Int();

初始化您的 POD 或声明标准构造函数以使其成为非 POD; 但您也可以出于性能原因使用未初始化的 POD,例如:

Int a;
a.i = 5;

【讨论】:

    【解决方案3】:

    不,对象a 未默认初始化。如果你想默认初始化它,你必须说:

    Int a = Int() ;
    

    【讨论】:

    • 哦,是的,它是默认初始化的。 Int a; 要求使用默认构造函数构造 aInt a = Int(); 要求使用默认构造函数构造一个临时的 Int 对象,然后使用这个临时构造复制构造 a,尽管编译器可以(并且很可能会)跳过复制构造函数和默认构造 a直接。
    • @TonyK @Thomas 无论如何,Int a = Int(); 怎么会被认为是默认初始化? Int() 用 0 初始化一个临时值,然后将其复制到 a 中。
    猜你喜欢
    • 2013-02-19
    • 2015-03-22
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多