简体   繁体   English

什么时候C ++ POD类型被零初始化?

[英]When do C++ POD types get zero-initialized?

Coming from a C background, I've always assumed the POD types (eg ints) were never automatically zero-initialized in C++, but it seems this was plain wrong! 来自C背景,我一直认为POD类型(例如整数)从未在C ++中自动进行零初始化,但似乎这是完全错误的!

My understanding is that only 'naked' non-static POD values don't get zero-filled, as shown in the code snippet. 我的理解是,只有'裸'非静态POD值不会被填零,如代码片段所示。 Have I got it right, and are there any other important cases that I've missed? 我做对了,还有其他重要的案例我错过了吗?

static int a;

struct Foo { int a;};

void test()
{
  int b;     
  Foo f;
  int *c = new(int); 
  std::vector<int> d(1);

  // At this point...
  // a is zero
  // f.a is zero
  // *c is zero
  // d[0] is zero
  // ... BUT ... b is undefined     
}  

Assuming you haven't modified a before calling test() , a has a value of zero, because objects with static storage duration are zero-initialized when the program starts. 假设你没有修改a调用前test() a具有零值,因为静态存储对象是在程序启动时初始化为零。

d[0] has a value of zero, because the constructor invoked by std::vector<int> d(1) has a second parameter that takes a default argument; d[0]的值为零,因为std::vector<int> d(1)调用的构造函数有第二个参数,它接受一个默认参数; that second argument is copied into all of the elements of the vector being constructed. 第二个参数被复制到正在构造的向量的所有元素中。 The default argument is T() , so your code is equivalent to: 默认参数是T() ,因此您的代码等效于:

std::vector<int> d(1, int());

You are correct that b has an indeterminate value. 你是正确的b有一个不确定的值。

fa and *c both have indeterminate values as well. fa*c也都有不确定的值。 To value initialize them (which for POD types is the same as zero initialization), you can use: 要初始化它们(对于POD类型与零初始化相同),您可以使用:

Foo f = Foo();      // You could also use Foo f((Foo()))
int* c = new int(); // Note the parentheses

Actually some of the values being zero may be due to you trying this code in the debug version of the application (if that is the case). 实际上,某些值为零可能是由于您在应用程序的调试版本中尝试此代码(如果是这种情况)。

If I'm not mistaken, in your code: 如果我没弄错,请在你的代码中:

  • a should be uninitialized. a应该是未初始化的。
  • b should be uninitialized b应该是未初始化的
  • c should point to a new (uninitialized) int c应该指向一个新的(未初始化的)int
  • d should be initialized to [0] (as you correctly guessed) d应初始化为[0](正如您猜测的那样)

Note that the zero-initialization done by the OS as a security feature is usually only done the first time memory is allocated. 请注意,操作系统作为安全功能执行的零初始​​化通常仅在第一次分配内存时完成。 By that I mean any segment in the heap, stack, and data sections. 我指的是堆,堆栈和数据部分中的任何段。 The stack and data sections are typically of fixed size, and are initialized when the application is loaded into memory. 堆栈和数据部分通常具有固定大小,并在应用程序加载到内存时初始化。

The data segment (containing static/global data and code) typically doesn't get "re-used", although that may not be the case if you dynamically load code at runtime. 数据段(包含静态/全局数据和代码)通常不会“重用”,但如果在运行时动态加载代码,情况可能并非如此。

The memory in the stack segment gets re-used all the time. 堆栈段中的内存会一直重用。 Local variables, function stack frames, etc.. are all being constantly used and re-used and are not initialized every time - just when the application is first loaded. 局部变量,函数堆栈帧等都经常被使用和重用,并且每次都没有初始化 - 就在首次加载应用程序时。

However, when the application makes requests for heap memory, the memory manager will typically zero-initialize segments of memory before granting the request, but only for new segments. 但是,当应用程序发出堆内存请求时,内存管理器通常会在授予请求之前对内存段进行零初始化,但仅限于新段。 If you make a request for heap memory, and there is free space in a segment that was already initialized, the initialization isn't done a second time. 如果您请求堆内存,并且已经初始化的段中有可用空间,则不会再次执行初始化。 Therefor, there is no guarantee that if that particular segment of memory is re-used by your application, it will get zero-initialized again. 因此,无法保证如果您的应用程序重新使用该特定内存段,它将再次进行零初始化。

So, for example, if you allocate a Foo on the heap, assign its field a value, delete the Foo instance, and then create a new Foo on the heap, there is a chance that the new Foo will be allocated in the same exact memory location as the old Foo, and so its field will initially have the same value as the old Foo's field. 因此,例如,如果在堆上分配Foo,为其字段分配值,删除Foo实例,然后在堆上创建新的Foo,则有可能新的Foo将以相同的方式分配内存位置为旧Foo,因此其字段最初将具有与旧Foo字段相同的值。

If you think about it, this makes sense, because the OS is only initializing the data to prevent one application from accessing the data from another application. 如果您考虑一下,这是有道理的,因为操作系统只是初始化数据以防止一个应用程序访问另一个应用程序的数据。 There is less risk in allowing an application access to its own data, so for performance reasons the initialization isn't done every time - just the first time a particular segment of memory is made available for use by the application (in any segment). 允许应用程序访问自己的数据的风​​险较小,因此出于性能原因,每次都不会进行初始化 - 只是第一次使特定的内存段可供应用程序使用(在任何段中)。

Sometimes when you run an application in debug mode, however, some debug mode runtimes initialize stack and heap data at every allocation (soo your Foo field will always be initialized). 但是,有时在调试模式下运行应用程序时,某些调试模式运行时会在每次分配时初始化堆栈和堆数据(因此,您的Foo字段将始终初始化)。 However, different debug runtimes initialize the data to different values. 但是,不同的调试运行时将数据初始化为不同的值。 Some zero initialize, and some initialize to a "marker" value. 有些零初始化,有些初始化为“标记”值。

The point is - never ever use uninitialized values anywhere in your code. 关键是 - 永远不要在代码中的任何地方使用未初始化的值。 There is absolutely no guarantee that they will be zero initialized. 绝对不能保证它们将被初始化为零。 Also, be sure to read the previously linked article regarding parens and default vs value initialization as this affects the definition of an "uninitialized" value. 此外,请务必阅读之前关于parens和默认值与值初始化的链接文章,因为这会影响“未初始化”值的定义。

For me, POD types are initialized depending on the part of the memory they are placed. 对我来说,POD类型根据它们所处的内存部分进行初始化。 Your static int a is allocated on the data segment, so it has a default value on startup. 您的static int a在数据段上分配,因此它在启动时具有默认值。 However, I think f is not inizialized in your example... 但是,我认为f在你的例子中没有被贬低......

They don't. 他们没有。 Debug bits versions might do this, but typically it's just placed into memory, and initialized to whatever happened to be the value in memory. 调试位版本可能会这样做,但通常它只是放入内存中,并初始化为内存中的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM