在下面的代码中
int main(){
int i;
for(i = 0;i<4;i++){
int x = 1;
x++;
} // for close
}// main close
这里变量x
是`自动存储类,对吗?
那么,变量x
是否会被创建,我的意思是内存分配在遇到语句时发生,当它到达循环结束时被破坏并且被创建/内存再次被分配给{{1} }?
我尝试在循环中打印x
的地址,并且每次都为x
打印相同的地址。所以,每次创建和销毁x并且它正在使用相同的房间/内存块吗?
如果它正在创建和破坏,那么它是否会影响CPU使用率? 如果是这样,有没有办法防止它并保持良好的记忆健康?
答案 0 :(得分:2)
简短的回答是&#34;没有&#34;。任何优化编译器都会优化此变量,因为它永远不会被读取。
即使关闭优化器,变量也会在进入函数时分配一次,然后在每次迭代中设置为1,然后再增加。
分配非常便宜,因为它在自动存储中。这个空间是在编译时决定的,因此在运行时它不需要任何费用。所有迭代都重用相同的位置,因此迭代不会产生额外的成本。
答案 1 :(得分:1)
是的,为循环中的每个回合构造和销毁变量。
但是,正如您所注意到的,编译器足够智能,每次都可以为变量重用相同的存储。可能在堆栈上,在输入函数时可以分配空间。所以没有必要担心“内存管理”。
如果你打开一些优化,编译器也可能会注意到没有任何变量真正用于任何事情,并删除所有代码。
答案 2 :(得分: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
答案 3 :(得分:0)
在for循环的每次迭代中,您创建变量'x',将其设置为1,并将其递增为2.'x'正在被销毁,因为它仅存在于for循环中。如果您不希望每次迭代都创建和销毁它,您可以简单地在for循环上面声明它。
但是你想用这段代码完成什么呢?它似乎没有做太多。此外,由于你担心内存分配,变量'i'可以在for循环中声明,这样你就可以在完成for循环后没有它。