Q015#
#include <iostream>
#include <exception>
int x = 0;
class A {
public:
A() {
std::cout << 'a';
if (x++ == 0) {
throw std::exception();
}
}
~A() {
std::cout << 'A';
}
};
class B {
public:
B() {
std::cout << 'b';
}
~B() {
std::cout << 'B';
}
A a;
};
void foo() {
static B b;
}
int main() {
try {
foo();
} catch (std::exception &) {
std::cout << 'c';
foo();
}
}
Answer#
click to see answer
acabBAExplain#
When calling the foo()
function within the try
block, a local static variable b
is defined in this function. When constructing the b
object, the member variable a
of class B
is constructed first. a
calls the default constructor of the A
object, outputting a, then checks x
, because it is post-increment (x++
), the check is x == 0
, performs the operation to throw an exception throw std::exception()
. Upon catching the exception with catch (std::exception &)
, it outputs c, and calls the foo()
function again. Inside the foo()
function, since the function was called within the try
block, the local static variable b
has not been fully initialized, so it will be initialized again. It constructs the member variable a
of class B
, calls the default constructor of the A
object, outputting a, then checks x
, where x != 0
, so it does not throw an exception. The construction of member variable a
is completed, and it starts calling the default constructor of B
, outputting b. After the program terminates, the local static variable b
begins to be destructed, calling the destructor of b
, outputting B, then calling the destructor of member variable a
, outputting A.
Throwing exceptions in constructors may result in partially constructed objects, which can lead to resource leaks or inconsistent object states, so it should be avoided.