以下短语在C ++中是什么意思:零,默认和值初始化?


188

以下短语在C ++中是什么意思:

  • 零初始化

  • 默认初始化,以及

  • 价值初始化

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



20
还有更多!初始化的完整列表:值,直接,副本,列表(C ++ 11新介绍),集合,引用,零,常量和默认值;en.cppreference.com/w/cpp/language/initialization列出了所有带有示例的示例:)
legends2k 2013年

Answers:


64

要意识到的一件事是,“值初始化”是C ++ 2003标准的新增功能-最初的1998标准中不存在(我认为这可能是唯一的区别,而不仅仅是澄清)。有关标准的直接定义,请参见Kirill V. Lyadvinsky的答案

有关operator new这些类型的初始化的不同行为及其启动的时间(以及从c ++ 98到C ++ 03的不同时间),请参见有关的行为的先前答复,以获取详细信息:

答案的重点是:

有时,new运算符返回的内存将被初始化,有时它并不取决于您要更新的类型是POD,还是它是包含POD成员并且正在使用编译器生成的默认构造函数的类。

  • 在C ++ 1998中,有两种初始化类型:零和默认
  • 在C ++ 2003的第三种初始化类型中,添加了值初始化。

至少可以说,这很复杂,并且在采用不同的方法时很微妙。

要知道的一件事是,即使在VS 2008(VC 9或cl.exe版本15.x)中,MSVC仍遵循C ++ 98规则。

以下代码段显示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;
}

1
并不重要int,但是m()在第三行,值初始化m。如果更改int m;为,则很重要B m;。:)
Johannes Schaub-litb

右键- AC在这个例子中,不使用(他们是从其他链接的答案结转)。即使C ++ 98和C ++ 03在描述AC构造时使用了不同的术语,但两个标准的结果是相同的。仅struct B导致不同的行为。
Michael Burr,

1
我的意思是,如果将C更改为struct C { C() : m() {}; ~C(); B m; };,则您将为m.m0。但是,如果m像您说的C ++ 03那样进行默认初始化,则m.m不会像在C ++ 98中那样进行初始化。
Johannes Schaub-litb 2010年

1
:在MSVC其他有趣的评论处理此功能的stackoverflow.com/questions/3931312/...
nobar

当您将类型声明为局部变量时(即在堆栈上),哪个初始化发生?
安德烈·佩尔(AndréPuel),2013年

87

C ++ 03标准8.5 / 5:

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

默认初始化的类型T的装置的对象:
-如果T是一个非POD类型(第9节),T的默认构造函数被调用(并形成不良的初始化如果T没有可访问的缺省的构造);
—如果T是数组类型,则每个元素都将默认初始化;
—否则,该对象将被初始化为零。

值初始化的类型T的装置的对象:
-如果T是一个类型(第9节)与用户声明的构造(12.1),然后对T中的默认构造函数被调用(以及初始化是形成不良的如果T没有可访问的默认构造函数);
—如果T是一个没有用户声明的构造函数的非联合类类型,则T的每个非静态数据成员和基类组件都将被值初始化;
—如果T是数组类型,则每个元素都进行值初始化;
—否则,该对象将被初始化为零

要求引用类型的实体进行默认初始化或值初始化的程序格式错误。如果T是cv限定类型,则T的cv非限定版本用于零初始化,默认初始化和值初始化的这些定义。


17
对于C ++ 11,这可能已过时。cppreference.com指出,默认初始化不会对成员进行零初始化(仅值初始化可以)。
Alexei Sholik 2013年

3
@android提出了一个重要的观点,我在其他地方看不到答案,因此我提出了一个新问题。 stackoverflow.com/questions/22233148/...
阿德里安·麦卡锡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.