C++ 中 POD 类型的默认初始化

2022-01-18 00:00:00 initialization c++

我知道一些 POD 变量是默认初始化的,但其他的是不是.(POD类型包括intfloat、指针、联合、POD类型的数组、POD类型的structs等)

I know some POD variables are initialized by default, but others are not. (POD types include int, float, pointers, unions, arrays of POD types, structs of POD types, etc.)

作用域和存储类如何影响 POD 类型的默认初始化?

具体来说,以下哪一项会被隐式初始化:

Specifically, which of the following will be initialized implicitly:

  • 具有自动存储功能的局部变量
  • 静态局部变量
  • 静态全局变量
  • 外部变量
  • new
  • 分配的变量
  • 类的 POD 成员(没有在构造函数中显式初始化)

我知道存在与其中一些情况相关的问题,但并不全面(它们只针对特定情况).

I know there are existing questions relating to some of these situations, but none comprehensive (they only address specific situations).

推荐答案

具有自动存储持续时间的局部变量未自动初始化.由于使用未初始化的变量会产生未定义的行为,因此最好显式初始化变量,即使它是多余的.

Local variables with automatic storage duration are not being initialized automatically. Since using uninitialized variables produces undefined behavior, it is a good practice to explicitly initialize your variables even when it's redundant.

关于被零初始化的 POD 类型,C++03 标准 3.6.2 非本地对象的初始化 声明:

About POD types that are being zero-initialized, C++03 standard 3.6.2 Initialization of non-local objects states:

§1 具有静态存储持续时间 (3.7.1) 的对象应在进行任何其他初始化之前零初始化 (8.5).零初始化和用常量表达式初始化统称为静态初始化;所有其他初始化都是动态初始化.使用常量表达式 (5.19) 初始化的具有静态存储持续时间的 POD 类型 (3.9) 的对象应在任何动态初始化发生之前进行初始化.

§1 Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place.

因此标准保证具有静态存储持续时间(无论它们的范围是什么)的 POD 类型将被零初始化.

So it's guaranteed by standard that POD types with static storage duration (whatever their scope is) will be zero-initialized.

类的 POD 成员(没有在构造函数中显式初始化)

这种情况在12.6.2 初始化基和成员中有所描述,说明(选定部分):

This situation is described in 12.6.2 Initializing bases and members, that states (selected parts):

如果给定的非静态数据成员或基类不是由mem-initializer-id命名的(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer),然后:

If a given nonstatic data member or base class is not named by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then:

――如果实体是非静态数据成员...,并且实体类是非POD类,实体是默认初始化的 (8.5)...

― If the entity is a nonstatic data member..., and the entity class is a non-POD class, the entity is default-initialized (8.5)...

― 否则实体未初始化...

在对类 X 的构造函数的调用完成后,如果 X 的成员既没有在构造函数的 mem-initializers 中指定,也没有默认初始化,也没有值初始化,也没有在执行主体期间给定值构造函数,成员的值不确定.

After the call to a constructor for class X has completed, if a member of X is neither specified in the constructor’s mem-initializers, nor default-initialized, nor value-initialized, nor given a value during execution of the body of the constructor, the member has indeterminate value.

例子:

class C
{
public:
    C(int x, int z) : x(x), z(z) { }
    int x, y, z;
};

int main(void)
{
    C* c = new C(1,3);
    std::cout << c->y; // value of y is undetermined !!!
}

相关文章