下面这些短语在c++中是什么意思:

zero-initialization, default-initialization, value-initialization

c++开发人员应该了解哪些?


当前回答

c++ 03标准8.5/5:

To zero-initialize an object of type T means: — if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T; — if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized; — if T is a union type, the object’s first named data member is zero-initialized; — if T is an array type, each element is zero-initialized; — if T is a reference type, no initialization is performed. To default-initialize an object of type T means: — if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); — if T is an array type, each element is default-initialized; — otherwise, the object is zero-initialized. To value-initialize an object of type T means: — if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); — if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized; — if T is an array type, then each element is value-initialized; — otherwise, the object is zero-initialized A program that calls for default-initialization or value-initialization of an entity of reference type is ill-formed. If T is a cv-qualified type, the cv-unqualified version of T is used for these definitions of zero-initialization, default-initialization, and value-initialization.

其他回答

c++ 03标准8.5/5:

To zero-initialize an object of type T means: — if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T; — if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized; — if T is a union type, the object’s first named data member is zero-initialized; — if T is an array type, each element is zero-initialized; — if T is a reference type, no initialization is performed. To default-initialize an object of type T means: — if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); — if T is an array type, each element is default-initialized; — otherwise, the object is zero-initialized. To value-initialize an object of type T means: — if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); — if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized; — if T is an array type, then each element is value-initialized; — otherwise, the object is zero-initialized A program that calls for default-initialization or value-initialization of an entity of reference type is ill-formed. If T is a cv-qualified type, the cv-unqualified version of T is used for these definitions of zero-initialization, default-initialization, and value-initialization.

需要意识到的一件事是,“值初始化”在c++ 2003标准中是新的——它在最初的1998标准中不存在(我认为这可能是唯一的区别,不仅仅是澄清)。参见Kirill V. Lyadvinsky对直接来自标准的定义的回答。

查看之前关于operator new行为的回答,了解这些类型初始化的不同行为以及它们何时开始生效(以及它们从c++98到c++ 03的不同之处):

类型名称后的括号与new有区别吗?

答案的要点是:

有时new操作符返回的内存将被初始化,有时则不初始化,这取决于新创建的类型是POD,还是包含POD成员并使用编译器生成的默认构造函数的类。 在c++ 1998中,有两种初始化类型:0和default 在c++ 2003中增加了第三种初始化类型,值初始化。

至少可以说,这是相当复杂的,当不同的方法起作用时是微妙的。

需要明确的一点是MSVC遵循c++ 98规则,即使在VS 2008 (VC 9或cl.exe版本15.x)中也是如此。

下面的代码片段显示MSVC和Digital Mars遵循c++ 98规则,而GCC 3.4.5和Comeau遵循c++ 03规则:

#include <cstdio>
#include <cstring>
#include <new>

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

int main()
{
    char buf[sizeof(B)];
    std::memset( buf, 0x5a, sizeof( buf));

    // use placement new on the memset'ed buffer to make sure 
    //  if we see a zero result it's due to an explicit 
    //  value initialization
    B* pB = new(buf) B();   //C++98 rules - pB->m is uninitialized
                            //C++03 rules - pB->m is set to 0
    std::printf( "m  is %d\n", pB->m);
    return 0;
}