-3

在下面的这段代码中

int main(){
int i;
for(i = 0;i<4;i++){
int x = 1;
x++;
} // for close
}// main close

这里的变量x是`auto storage class,对吧?

那么,变量x会被创建吗,我的意思是内存分配发生在遇到语句时,当它到达循环结束并被创建/内存被再次分配时被销毁x

我试图打印x循环中的地址,它每次都打印相同的地址x。那么,这是否意味着每次创建和销毁 x 并且它使用相同的房间/内存块?

如果它像那样创建和销毁,它不会影响CPU使用率吗?如果是这样,有什么方法可以预防并保持良好的记忆健康?

4

4 回答 4

2

简短的回答是“没有”。任何优化编译器都会优化这个变量,因为它永远不会被读取。

即使关闭优化器,变量也会在进入函数时分配一次,然后在每次迭代中设置为 1,然后是增量。

分配非常便宜,因为它在自动存储中。空间是在编译时决定的,所以在运行时它不会花费你任何东西。所有迭代都重用相同的位置,因此不会因迭代而产生额外成本。

于 2017-04-01T18:14:57.730 回答
1

是的,变量在循环中的每一轮都被构造和销毁。

但是,正如您所注意到的,编译器足够聪明,每次都可以为变量重用相同的存储空间。可能在堆栈上,当进入函数时,空间可能已经被分配。因此无需担心“内存管理”。

如果你开启一些优化,编译器也可能会注意到没有一个变量真正用于任何事情,并删除所有代码。

于 2017-04-01T18:15:56.303 回答
1

它取决于实现。您会看到相同的内存地址,因为编译器决定这样做。在每次迭代之前,内存不会神奇地分配到新地址。架构中的自动存储x86是使用堆栈实现的,分配只是通过减法ESP/ RSP(x86/x64) 寄存器完成,它指向堆栈的顶部。您可以在互联网上阅读有关它的文章。

编译器只是在每次迭代时重新分配内存(不分配/解除分配)

这是您的代码(GCC 6.3、x86)的汇编列表。汇编语言中的注释以;. 我添加了类似c的伪代码来解释指令的含义

main:
        push    ebp
        mov     ebp, esp ; Create new stack frame
        sub     esp, 16 ; Allocate memory for local variables
        mov     DWORD PTR [ebp-4], 0 ; i = 0;
.L3:
        cmp     DWORD PTR [ebp-4], 3  ; if(i > 3)
                                      ; {
        jg      .L2                   ;    break;
                                      ; }
        mov     DWORD PTR [ebp-8], 1 ; x = 1;
        add     DWORD PTR [ebp-8], 1 ; x += 1;
        add     DWORD PTR [ebp-4], 1 ; i += 1;
        jmp     .L3 ; Go to location .L3
.L2:
        mov     eax, 0 ; Set return value to 0
        leave ; Restore the stack pointer
        ret ; Return to the caller

所以ebp - 8(或int x)的地址每次都相同。

这是优化的代码汇编列表(GCC 6.3,֊O3,x86)。

main:
        xor     eax, eax ; Set return value to 0
        ret ; Return to the caller
于 2017-04-01T18:31:58.517 回答
0

在 for 循环的每次迭代中,您将创建变量“x”,将其设置为 1,然后将其递增为 2。“x”正在被销毁,因为它仅存在于 for 循环中。如果您不希望每次迭代都创建和销毁它,您可以简单地在 for 循环上方声明它。

但是,您到底想用这段代码完成什么?它似乎没有多大作用。此外,由于您担心内存分配,因此可以在 for 循环中声明变量“i”,这样您就不会在完成 for 循环后让它徘徊。

于 2017-04-01T18:16:05.903 回答