运算符new将内存初始化为零

时间:2011-09-25 15:51:00

标签: c++ memory-management

有这样的代码:

#include <iostream>

int main(){
  unsigned int* wsk2 = new unsigned int(5);
  std::cout << "wsk2: " << wsk2 << " " << *wsk2 << std::endl;
  delete wsk2;
  wsk2 = new unsigned int;
  std::cout << "wsk2: " << wsk2 << " " << *wsk2 << std::endl;
  return 0;
}

结果:

wsk2: 0x928e008 5
wsk2: 0x928e008 0

我已经读过new没有用零初始化内存。但似乎它确实如此。它是如何工作的?

4 个答案:

答案 0 :(得分:154)

有两个版本:

wsk = new unsigned int;      // default initialized (ie nothing happens)
wsk = new unsigned int();    // zero    initialized (ie set to 0)

也适用于数组:

wsa = new unsigned int[5];   // default initialized (ie nothing happens)
wsa = new unsigned int[5](); // zero    initialized (ie all elements set to 0)

回答以下评论。

  

嗯...你确定new unsigned int[5]()将整数归零吗?

显然是的:

  

[C ++ 11:5.3.4 / 15]:创建类型为T的对象的new-expression初始化该对象,如下所示:如果省略new-initializer,则默认初始化该对象(8.5) ;如果没有执行初始化,则该对象具有不确定的值。否则,根据8.5的初始化规则解释new-initializer以进行直接初始化。

#include <new>
#include <iostream>


int main()
{
    unsigned int   wsa[5] = {1,2,3,4,5};

    // Use placement new (to use a know piece of memory).
    // In the way described above.
    // 
    unsigned int*    wsp = new (wsa) unsigned int[5]();

    std::cout << wsa[0] << "\n";   // If these are zero then it worked as described.
    std::cout << wsa[1] << "\n";   // If they contain the numbers 1 - 5 then it failed.
    std::cout << wsa[2] << "\n";
    std::cout << wsa[3] << "\n";
    std::cout << wsa[4] << "\n";
}

结果:

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.2.0
Thread model: posix
> g++ t.cpp
> ./a.out
0
0
0
0
0
>

答案 1 :(得分:19)

operator new无法保证将内存初始化为任何内容,并且在没有 new-initializer 的情况下分配unsigned int new-expression 会离开具有不确定值的对象。

读取未初始化对象的值会导致未定义的行为未定义的行为包括评估零值而没有任何不良影响但可能导致任何事情发生,因此您应该避免导致它。

在C ++ 11中,使用的语言是分配的对象是 default-initialized ,对于非类类型,这意味着不执行初始化。这与C ++ 03中 default-initialized 的含义不同。

答案 2 :(得分:4)

对于一些编译器,new的调试版本将初始化数据,但肯定没有什么可以依赖。

内存也可能只是之前使用过的0。不要假设删除和新内存之间没有任何内容发生。在背景中可能会有一些你从未注意到的事情。此外,相同的指针值可能不是相同的物理内存。内存页面被移动并被分页输入。指针可能被映射到一个完全不同的位置。

结论:如果你没有专门初始化一个内存位置,那么你可以不假设它的内容。在使用内存之前,内存管理器甚至可能不会分配特定的物理内存位置。

现代内存管理非常复杂,但作为一名C ++程序员,你并不关心(主要是‡)。遵守规则,你不会遇到麻烦。

‡如果您正在优化以减少页面错误,您可能会在乎。

答案 3 :(得分:3)

那不是operator new,那是new运营商。实际上有很大的不同!不同之处在于operator new是一个返回原始内存的函数;当您使用new运算符时,它会为您调用构造函数。它是构造函数设置int的值,而不是operator new