在这个 C 代码片段中:
void func(void)
{
int x=10;
if (x>2)
{
int y=2;
//block statement
{
int m=12;
}
}
else
{
int z=5;
}
}
x,y,z 和 m 何时从 func 堆栈帧中分配和释放?
实际分配取决于您的编译器,但许多编译器在函数开始时在堆栈上分配空间,并在函数返回之前释放它。请注意,这与变量实际可访问的时间是分开的,即直到定义它们的块的末尾。
在您的示例中,启用优化后,编译器可能不会在堆栈上为您的变量分配任何空间并简单地返回,因为它可以在编译时确定该函数实际上没有任何效果。
根据 C++ 规则,您应该认为每个局部变量都在其块的末尾被销毁。这是调用析构函数的时间。但是,编译器可能会决定在函数的开头/结尾一起分配/取消分配所有局部变量,这就是 VC++ 编译器所做的:
void func(void)
{
001413B0 push ebp
001413B1 mov ebp,esp
001413B3 sub esp,0F0h
001413B9 push ebx
001413BA push esi
001413BB push edi
001413BC lea edi,[ebp-0F0h]
001413C2 mov ecx,3Ch
001413C7 mov eax,0CCCCCCCCh
001413CC rep stos dword ptr es:[edi]
int x=10;
001413CE mov dword ptr [x],0Ah
if (x>2)
001413D5 cmp dword ptr [x],2
001413D9 jle func+3Bh (1413EBh)
{
int y=2;
001413DB mov dword ptr [y],2
//block statement
{
int m=12;
001413E2 mov dword ptr [m],0Ch
}
}
else
001413E9 jmp func+42h (1413F2h)
{
int z=5;
001413EB mov dword ptr [z],5
}
}
但这些是实现细节,编译器可以通过另一种方式自由调整堆栈指针。
因此,没有定义实际的堆栈指针调整,但构造函数/析构函数调用完全根据函数内部块完成。当然,您不能在其块之外使用变量 - 这不是编译的。尽管此时可能会分配堆栈空间。