操作员将内存初始化为零
有这样的代码:
#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
不用零初始化内存。 但是在这里看起来确实如此。 它是如何工作的?
有两个版本:
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)
回答下面的评论。
呃…你确定新的unsigned int5是整数吗?
显然是的:
[C ++ 11:5.3.4 / 15]:创buildtypes为T的对象的新expression式将按如下所示初始化该对象:如果省略了新初始化程序,则该对象将被默认初始化(8.5)。 如果没有执行初始化,则该对象具有不确定的值。 否则,按照8.5的初始化规则对新的初始化器进行解释以进行直接初始化。
#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 >
operator new
不保证将内存初始化为任何内容,并且在没有new-initializer的情况下分配unsigned int
的newexpression式将使对象具有不确定的值。
读取未初始化的对象的值会导致未定义的行为 。 未定义的行为包括评估零值,没有不良影响,但可能导致任何事情发生,所以你应该避免造成它。
在C ++ 11中,使用的语言是分配的对象是默认初始化的 ,对于非类types来说,这意味着不执行初始化。 这与C ++ 03中默认初始化的含义不同。
这不是operator new
的operator new
,那是new
运营商。 其实有一个很大的区别! 不同之处在于operator new
是返回原始内存的函数。 当你使用new
运算符时,它会为你调用一个构造函数。 这是设置该int
的值,而不是operator new
的构造函数。
有了一些编译器,new的debugging版本将会初始化数据,但肯定没有什么可以依赖的。
内存也可能是从以前的使用0。 不要以为在删除和新build之间没有任何内存发生。 在背景中可能有一些你从未注意过的东西。 而且,相同的指针值可能不是相同的物理内存。 内存页面被移动并分页input。指针可能被映射到与之前完全不同的位置。
底线:如果你没有专门初始化一个内存位置,那么你可以不假设它的内容。 内存pipe理器可能不会分配一个特定的物理内存位置,直到您使用内存。
现代内存pipe理非常复杂,但作为一名C ++程序员,你并不在意(主要是‡)。 玩规则,你不会陷入困境。
‡如果您正在优化以减less页面错误,您可能会关心。