以下短语在 C++ 中意味着什么:零初始化、默认初始化和值初始化?

发布于 08-08 21:55 字数 131 浏览 7 评论 0原文

以下短语在 C++ 中的含义是什么:

  • 零初始化、

  • 默认初始化和

  • 值初始化

C++ 开发人员应该了解它们什么?

What do the following phrases mean in C++:

  • zero-initialization,

  • default-initialization, and

  • value-initialization

What should a C++ developer know about them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

回忆那么伤2024-08-15 21:55:02

C++03 标准 8.5/5:

对 T 类型的对象进行零初始化意味着:
— 如果 T 是标量类型 (3.9),则将对象设置为转换为 T 的 0(零)值;
— 如果 T 是非联合类类型,则每个非静态数据成员和每个基类子对象均为零初始化;
— 如果 T 是联合类型,则对象的第一个命名数据成员为零初始化;
— 如果 T 是数组类型,则每个元素均初始化为零;
— 如果 T 是引用类型,则不执行初始化。

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

对 T 类型的对象进行值初始化意味着:
— 如果 T 是具有用户声明的构造函数 (12.1) 的类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化格式错误);
— 如果 T 是没有用户声明的构造函数的非联合类类型,则 T 的每个非静态数据成员和基类组件都是值初始化的;
— 如果 T 是数组类型,则每个元素都是值初始化的;
— 否则,该对象将被零初始化

调用引用类型实体的默认初始化或值初始化的程序格式不正确。如果 T 是 cv 限定类型,则 T 的 cv 非限定版本将用于零初始化、默认初始化和值初始化的这些定义。

C++03 Standard 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.

如何视而不见2024-08-15 21:55:02

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

请参阅之前有关 operator new 行为的答案,详细了解这些类型的初始化的不同行为以及它们何时启动(以及它们何时从 c++98 到 C++03 有所不同) :

的要点答案是:

有时 new 运算符返回的内存会被初始化,有时则不会初始化,具体取决于您要新建的类型是否是 POD,或者是否是包含 POD 成员并正在使用编译器的类 -生成的默认构造函数。

  • 在 C++1998 中,有两种类型的初始化:零和默认
  • 在 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;
}

One thing to realize is that 'value-initialization' is new with the C++ 2003 standard - it doesn't exist in the original 1998 standard (I think it might be the only difference that's more than a clarification). See Kirill V. Lyadvinsky's answer for the definitions straight from the standard.

See this previous answer about the behavior of operator new for details on the the different behavior of these type of initialization and when they kick in (and when they differ from c++98 to C++03):

The main point of the answer is:

Sometimes the memory returned by the new operator will be initialized, and sometimes it won't depending on whether the type you're newing up is a POD, or if it's a class that contains POD members and is using a compiler-generated default constructor.

  • In C++1998 there are 2 types of initialization: zero and default
  • In C++2003 a 3rd type of initialization, value initialization was added.

To say they least, it's rather complex and when the different methods kick in are subtle.

One thing to certainly be aware of is that MSVC follows the C++98 rules, even in VS 2008 (VC 9 or cl.exe version 15.x).

The following snippet shows that MSVC and Digital Mars follow C++98 rules, while GCC 3.4.5 and Comeau follow the C++03 rules:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文