正常题: 抛出时栈回溯 (stack unwinding)#
抛出异常时, 控制流沿着栈 向上 进行回溯, 直到找到一个能 匹配 到的 try-catch
块, 如果没能找到, 则调用 std::terminate
终止程序.
自动存储期对象是分配在栈上的 (具体地, 分配在代码块 {} 之内), 因此当抛出异常而发生栈回溯时, 若栈回溯离开了代码块 (函数代码块、try-catch
块、自行添加的 {}
等), 则会依次析构 已构造但尚未销毁的自动存储期对象, 以它们的构造函数完成的逆序调用析构函数.
提示
如果不理解什么是栈, 请进行 断点调试, 其中:
调用堆栈显示的就是栈的内容, 各行是对应函数调用的记录 (如局部变量等), 称为栈帧. 如果对递归函数进行断点调试就会发现, 每次调用都创建了新的栈帧, 即可以理解为单纯就是调用了新的函数, 所以递归函数的调用与普通函数的调用是完全一致的.
局部变量窗口显示的就是栈帧中的局部变量内容, 因此当栈回溯过程离开了该局部变量所在的代码块, 自然会析构掉其中 已构造但尚未销毁的自动存储期对象.
题 1#
1void function() {
2 Printer c1{Info{.ctor = "c", .dtor = "n"}};
3
4 try {
5 throw 1;
6 } catch (int) {
7 std::cout << "i";
8 }
9}
10
11int main() {
12 function();
13}
点击查看提示
3 个字符, C++ 标准输入流.
点击查看答案
[在线代码 ThTaW6qnM], 答案: cin
.
题 2#
try-catch
块也是代码块.
1void function() {
2 Printer c1{Info{.ctor = "s", .dtor = "n"}};
3 try {
4 Printer c2{Info{.ctor = "t", .dtor = "r"}};
5 throw 1;
6 } catch (int) {
7 Printer c3{Info{.ctor = "l", .dtor = "e"}};
8 }
9}
10
11int main() {
12 function();
13}
点击查看提示
6 个字符, 获取 C 风格字符串的长度.
点击查看答案
[在线代码 vMo9Kv6K6], 答案: strlen
.
题 3#
1void function1() {
2 Printer c1{Info{.ctor = "O", .dtor = "F"}};
3 throw 1.0;
4}
5
6void function2() {
7 Printer* c1 = new Printer{Info{.ctor = "E", .dtor = "I"}};
8 function1();
9 Printer c2{Info{.ctor = "H", .dtor = "L"}};
10}
11
12int main() {
13 try {
14 function2();
15 } catch (double) {
16 }
17}
点击查看提示
3 个字符, 输入流读取到流结束时产生的标志.
点击查看答案
[在线代码 6nvf1bj5j], 答案: EOF
.
题 4#
catch
块判断是否匹配时, 与判断函数是否匹配的方式不同, 不正式地说, 它不会进行大部分隐式类型转换.
1void function1() {
2 try {
3 Printer c1{Info{.ctor = "i", .dtor = "n"}};
4 throw 1;
5 } catch (double) {
6 }
7}
8
9void function2() {
10 Printer* c1 = new Printer{Info{.ctor = "c", .dtor = "u"}};
11 function1();
12 Printer c2{Info{.ctor = "o", .dtor = "t"}};
13}
14
15int main() {
16 try {
17 function2();
18 } catch (int) {
19 }
20}
点击查看提示
3 个字符, 标准输入流.
点击查看答案
[在线代码 7TEqd7arP], 答案: cin
.
题 5#
catch
块判断是否匹配时, 异常对象可以与其 公用基类 匹配.
1class Base {};
2
3class Derived : public Base {};
4
5void function1() {
6 try {
7 Printer c1{Info{.ctor = "r", .dtor = "o"}};
8 throw Derived{};
9 } catch (Base&) {
10 }
11}
12
13void function2() {
14 Printer* c1 = new Printer( Info{.ctor = "f", .dtor = "z"} );
15 function1();
16 Printer c2(Info{.ctor = "n", .dtor = "t"});
17}
18
19int main() {
20 try {
21 function2();
22 } catch (Derived&) {
23 }
24}
点击查看提示
5 个字符, 如何获取 vector 的首元素?
点击查看答案
[在线代码 7nzo55zPv], 答案: front
.