以下短语在 C++ 中的含义是什么:零初始化、默认初始化和值初始化?

StackOverflow https://stackoverflow.com/questions/1613341

  •  06-07-2019
  •  | 
  •  

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

  • 零初始化,

  • 默认初始化,以及

  • 值初始化

C++ 开发人员应该了解哪些关于它们的知识?

有帮助吗?

解决方案

需要认识到的一件事是“值初始化”是 C++ 2003 标准中的新内容 - 它在最初的 1998 标准中不存在(我认为这可能是唯一的区别,不仅仅是澄清)。看 基里尔五世利亚德文斯基的回答 直接来自标准的定义。

请参阅之前关于行为的答案 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 <stdio.h>
#include <string.h>
#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)];
    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
    printf( "m  is %d\n", pB->m);
    return 0;
}

其他提示

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 非限定版本将用于零初始化、默认初始化和值初始化的这些定义。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top