C ++数组初始化了什么?

时间:2013-09-29 00:30:30

标签: c++ memory

所以我可以手动解决这个问题,所以这不是一个紧急问题,但我认为这很奇怪:

在发生奇怪事情之前,这是我的全部代码:

int main(int argc, char** arg) {

int memory[100];
int loadCounter = 0;
bool getInput = true;
print_memory(memory);

然后是其他一些不相关的东西。

打印内存只打印应该初始化为全零的数组,而不是前几个数字:

+1606636544 +32767 +1606418432 +32767 +1856227894 +1212071026 +1790564758 +813168429 +0000 +0000

(加号和填充零只用于格式化,因为一旦数组填满,所有数字应该是0-1000。列表的其余部分是零)

它也不是内存泄漏,因为我尝试初始化一个不同的数组变量,并且在第一次运行时它也给了我很多奇怪的数字。为什么会这样?

5 个答案:

答案 0 :(得分:2)

既然你问过“C ++数组初始化了什么?”,答案就是它们会在它们进入范围时初始化到它们已被分配的内存中。 即它们未初始化

请注意,某些编译器会在调试版本中将堆栈变量初始化为零;一旦你开始进行发布版本,这可能会导致令人讨厌的,随机发生的问题。

答案 1 :(得分:1)

您正在使用的数组是堆栈分配:

int memory [100];

当特定功能范围退出(在本例中为main)或返回时,内存将被回收并且不会泄漏。这就是堆栈分配内存的工作原理。在这种情况下,您在堆栈上分配了100个整数(在我的编译器上各为32位),而不是在堆上。堆分配只是存储器中的其他位置,希望远离堆栈。无论如何,堆分配的内存有泄漏的机会。

表示在堆栈上分配的低级普通旧数据(就像您在代码中编写的那样)

你在函数中得到随机值的原因可能是因为你没有初始化'memory'整数数组中的数据。在发布模式下,应用程序或C运行时(至少在Windows中)不会将该内存初始化为已知的基值。因此,阵列中的内存是上次堆栈使用该内存时遗留的内存。它可能是几毫秒(很可能)到几秒钟(不太可能)到几分钟(不太可能)。无论如何,它被认为是垃圾记忆,并且不惜一切代价避免它。

问题是我们不知道你的函数叫什么print_memory。但是,如果该函数不以任何方式改变内存,那么就可以解释为什么你会得到看似随机的值。在使用它们之前,您需要先将这些值初始化为某些值。我喜欢这样声明我的基于堆栈的缓冲区:

int memory [100] = {0};

这是编译器用零填充整个数组的快捷方式。 它也适用于字符串和任何其他基本数据类型:

char MyName [100] = {0}; float NoMoney [100] = {0};

不确定您使用的是哪种编译器,但如果您在Visual Studio中使用微软编译器,那么您应该没问题。

答案 2 :(得分:1)

除了其他答案,请考虑以下因素:什么是数组?

在托管语言(如Java或C#)中,您可以使用高级抽象。 C和C ++不提供抽象(我的意思是硬件抽象,而不是像OO功能那样的语言抽象)。它们被设计为接近金属,即语言直接使用硬件(在这种情况下是内存),没有抽象。

这意味着当您声明局部变量int a时,编译器所做的就是说“ Ok,我将把内存块[A,A + sizeof(int)]解释为整数,我称之为'a'“(其中A是该块的开头与函数堆栈帧的起始地址之间的偏移量)。 如您所见,编译器仅“将”内存段“分配”给变量。它没有做任何“魔术”,比如“创造”变量。您必须了解您的代码在计算机中执行,并且计算机只有内存和CPU 。没有魔力。

那么函数执行开始时变量的值是多少? 用变量的内存块表示的数据表示的值。通常,从我们当前的观点来看,这些数据没有任何意义(例如,可能是字符串之前使用的数据的一部分),因此当您访问该变量时,您将获得额外值。 这就是我们所谓的“垃圾”:以前写过的数据在我们的背景下没有任何意义。

同样适用于数组:数组只是更大的内存块,有足够的空间来容纳数组的所有值:[A,A + (length of the array)*sizeof(type of array elements)]。因此在变量的情况下,内存包含垃圾

通常,您希望在声明期间使用一组值初始化数组。您可以使用初始化列表实现此目的:

int array[] = {1,2,3,4};

在这种情况下,编译器会向函数添加代码,以初始化数组与该值相关的内存块。

旁注:非POD类型和静态存储

上面解释的内容仅适用于POD types,例如基本类型和基本类型数组。对于类之类的非POD类型,编译器会添加对变量构造函数的调用,这些变量用于初始化类实例的值(属性)。

此外,即使您使用POD类型,如果变量具有static storage specification,编译器也会使用默认值初始化其内存,因为静态变量是在程序启动时分配的。

答案 3 :(得分:0)

堆栈上的局部变量未在c / c ++中初始化。 c / c ++设计得很快,所以在函数调用时不会叠加零。

答案 4 :(得分:0)

main()运行之前,语言运行库会设置环境。正是它正在做的事情你必须通过打破加载模块的入口点并观察堆栈指针来发现,但无论如何,进入main时的堆栈空间不能保证干净。

任何需要干净堆栈或mallocnew空间的东西都可以自行清理它。很多事情都没有。 C [++]不是在做不必要的事情。在C ++中,一个类对象可以有隐式运行的非平凡构造函数,它们保证对象的设置使用,但是数组和普通标量没有构造函数,如果你想要一个初始值,你必须声明一个初始化器。