【问题标题】:What happens if an exception occur before than static local variables are initialized?如果在初始化静态局部变量之前发生异常会发生什么?
【发布时间】:2016-11-26 18:04:52
【问题描述】:

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

考虑闲置代码:

#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?

【问题讨论】:

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


    【解决方案1】:

    每次控制越过变量定义时,都会尝试初始化具有静态存储持续时间的块范围变量,直到成功为止。

    来自 [stmt.dcl]/4:

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

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

    【讨论】:

    • 并且按照静态变量的破坏顺序,它不会有任何影响?
    • @Adib:我不明白——对什么有影响?静态变量按其构造的相反顺序被销毁(当然,这仅在构造实际发生时才相关)。
    • 是的,我确实想知道这一点,因为静态变量不是在异常之前构造的,所以它不会改变破坏顺序。对吗?
    • @Adib:只有对象会被销毁。如果没有对象,就没有可破坏的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 2012-01-07
    • 2011-03-30
    相关资源
    最近更新 更多