如果在初始化静态局部变量之前发生异常会怎样?

What happens if an exception occur before than static local variables are initialized?

静态局部变量什么时候初始化? 如果在构造函数中抛出异常,是否认为该对象已构造?析构函数会被调用吗?

考虑休闲代码:

#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();
  }
}

输出:acabBA

第一次调用 foo() 时,尝试初始化 b。它的构造函数被调用,它首先构造所有成员变量。这意味着 A::A() 被调用,打印 a. A::A() 然后抛出异常,构造函数被中止,b 或 B::a 实际上都没有被视为已构造。

为什么 b 第一次没有初始化?

每次控制通过变量定义时都会尝试初始化具有静态存储持续时间的块作用域变量,直到成功。

来自 [stmt.dcl]/4:

Dynamic initialization of a block-scope variable with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.

B 类型对象的构造当然不能完成,如果其任何成员的构造抛出异常。