当一些局部变量超出范围时,就会发生堆栈展开。
究竟如何调用析构函数?
我想知道编译器能够调用堆栈上对象的析构函数而不是堆上对象的析构函数的机制。
析构函数调用由编译器在生成的代码中发出。
例如,
void foo() {
A a;
}
编译为:
void foo() {
A::A(<stack-address-of-a>);
A::~A(<stack-address-of-a>);
}
当函数提前返回时,它会稍微复杂一些;考虑
void foo(int i) {
A a;
if (i) return;
B b;
}
就像
void foo() {
A::A(<stack-address-of-a>);
B::B(<stack-address-of-b>);
if (i) goto destroy_a;
B::~B(<stack-address-of-b>);
destroy_a:
A::~A(<stack-address-of-a>);
}
异常又有点复杂了;通常的解决方案涉及将必要的析构函数调用与调用堆栈相关联的异常区域和范围。有关概述,请参阅LLVM 中的异常处理。
由于它是一个堆栈(FILO),因此以相反的顺序调用析构函数。所以最后创建的对象将首先被销毁。
我想知道编译器能够调用堆栈上对象的析构函数的机制
好吧,如果它将某些东西放入堆栈,它应该知道如何将其从堆栈中弹出,这似乎是有道理的……调用是在编译过程中添加的。