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

时间:2016-11-26 18:04:53

标签: c++ c++11 exception static-initialization

何时初始化静态局部变量? 如果在构造函数中抛出异常,是否构造了对象?析构函数会被调用吗?

考虑暂停代码:

#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第一次没有初始化?

1 个答案:

答案 0 :(得分:3)

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

来自[stmt.dcl] / 4:

  

动态初始化具有静态存储持续时间(3.7.1)或线程存储的块范围变量   持续时间(3.7.2)是在控制第一次通过其声明时执行的;考虑这样的变量   初始化完成后初始化。 如果初始化通过抛出异常退出,则   初始化未完成,因此下次控件进入声明时将再次尝试。

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