C ++循环,范围和堆栈(为什么这样做?)

时间:2014-03-03 00:28:09

标签: c++ scope stack

我发现很难找到这样的问题的具体答案,但我会解释我认为这应该(不)工作的方式,也许有人可以告诉我我在哪里&# 39;我错了。

我在main中创建一个大小为10的整数数组,它存在于堆栈中。然后我使用for循环将整数0-9加载到该数组中。当for循环结束时,堆栈指针返回到初始化arr1之后的位置,但这些值仍然存在于内存中,并且数组仍然指向它们。

然后,我使用另一个for循环来泛洪堆栈,它应该覆盖在第一个for循环中创建的值,现在当我去访问arr1中的值时,它们应该指向值为5000的整数。

当我打印数组时,它仍然打印出数字0-9。为什么这样做?我认为当循环超出范围时,循环中声明的数据会从堆栈中弹出。感谢

int main(void)
{
    int arr1[10];

    for(int i = 0; i < 10; i++)
        arr1[i] = i;

    for(int i = 0; i < 500; i++)
        int a = 5000;

    for(int i = 0; i < 10; i++)
        cout << arr1[i] << endl;

    system("PAUSE");

    return 0;
}

4 个答案:

答案 0 :(得分:2)

不,数组不是“指向”值。 arr1是10个整数,它不是10个整数指针。值存储在数组中。创建并立即销毁另一个变量a,即使执行500次,也不会更改数组arr1中存储的内容。

您可能来自一种语言,根据定义,变量和/或数组元素是对象的引用。在C ++中并非如此。

对于它的价值,当你进入和退出for循环时,C ++实现通常不会移动堆栈指针。通常它们只为每个函数生成一个包含所有函数需要的变量的堆栈帧,尽管只要它们在正确的时间调用析构函数,它们就可以做他们喜欢的事情。

答案 1 :(得分:2)

您似乎在C ++中误解了数据生命周期。当在作用域块中声明本地数据时(无论是在函数,循环还是其他控制结构中),它将保留在堆栈中,直到该作用域块结束。

这意味着arr1的全部内容仍然会分配到堆栈中,直到main()完成,无论你做什么。它不会被同一函数中的后续局部变量覆盖,也不会被嵌套在更深的范围块中的变量覆盖。

在第二个循环中,变量a(理论上)在循环体的每次迭代上创建和销毁。这意味着你在循环期间堆栈上没有500个a实例 - 你只有一个。 (实际上,编译器几乎肯定会优化它,因为它没有做任何有用的事情。)

答案 2 :(得分:0)

正如你所说的那样“当循环中超出范围时,循环中声明的数据会从堆栈中弹出。”那是真实的。但是在您的示例中,数组未在循环内声明。它在循环之外声明,并且仍然在main()的其余部分的范围内。

如果你有这样的事情:

 char * arr1[10];

 for(int i = 0; i < 10; i++)
 {
     char * text[16];
     sprintf(text, "%d", i);
     arr1[i] = text;
 }
 for(int j = 0; j < 10; ++j)
     printf ("%s\n", arr1[i]);

然后这会崩溃,因为text []数组在第一个循环内声明,并且它们在循环结束时超出范围,留下指向超出范围的变量的指针。我想这就是你的想法。

答案 3 :(得分:0)

arr1a位于完全独立的内存位置。你可以用这一行证明这一点:

printf("%lu %p %p %p", \
    sizeof(int), (void *)&arr1[0], \
    (void *)&arr1[9], (void *)&a);

例如,在我的机器上我得到了这个输出:

  

4 0x7fff5541e640 0x7fff5541e664 0x7fff5541e63c

如您所见,&a是来自sizeof(int)的第一个元素的四个字节(arr1)。

以下声明:

for(int i = 0; i < 500; i++)
    int a = 5000;

没有你怀疑的效果。它只是一次又一次地将值5000分配给变量a,或者已经过优化,只进行一次甚至完全没有,因为未使用a