在运行时从函数调用栈中删除函数条目的过程称为栈展开。栈展开通常与异常处理有关。在C ++中, 当发生异常时, 将在函数调用栈中线性搜索异常处理程序, 并将带有异常处理程序的函数之前的所有条目从函数调用栈中删除。因此, 如果未在同一函数中(抛出异常的地方)处理异常, 则异常处理涉及栈展开。
例如, 以下程序的输出是:
f3() Start
f2() Start
f1() Start
Caught Exception: 100
f3() End
#include <iostream>
using namespace std;
// A sample function f1() that throws an int exception
void f1() throw ( int ) {
cout<< "\n f1() Start " ;
throw 100;
cout<< "\n f1() End " ;
}
// Another sample function f2() that calls f1()
void f2() throw ( int ) {
cout<< "\n f2() Start " ;
f1();
cout<< "\n f2() End " ;
}
// Another sample function f3() that calls f2() and handles exception thrown by f1()
void f3() {
cout<< "\n f3() Start " ;
try {
f2();
}
catch ( int i) {
cout<< "\n Caught Exception: " <<i;
}
cout<< "\n f3() End" ;
}
// A driver function to demonstrate Stack Unwinding process
int main() {
f3();
getchar ();
return 0;
}
在上述程序中, 当f1()引发异常时, 其条目从函数调用栈中删除(因为f1()不包含所引发异常的异常处理程序), 然后在调用栈中查找下一个条目以查找异常处理程序。下一个条目是f2()。由于f2()也没有处理程序, 因此其条目也会从函数调用栈中删除。函数调用栈中的下一个条目是f3()。由于f3()包含异常处理程序, 因此将执行f3()内部的catch块, 最后执行catch块之后的代码。请注意, 根本不执行f1()和f2()内部的以下行。
//inside f1()
cout<< "\n f1() End " ;
//inside f2()
cout<< "\n f2() End " ;
附带说明一下, 如果f1()和f2()内有一些本地类对象, 则在栈展开过程中将调用这些本地对象的析构函数。
如果未在同一函数中处理异常, 则Java中也会发生栈展开。
如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。
被认为是行业中最受欢迎的技能之一, 我们拥有自己的编码基础C++ STL通过激烈的问题解决过程来训练和掌握这些概念。