c – 从类成员初始化器抛出的异常是否调用std :: terminate()?

前端之家收集整理的这篇文章主要介绍了c – 从类成员初始化器抛出的异常是否调用std :: terminate()?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
给出这个代码
struct A {
    A(int e) { throw e; }
};

struct B {
    A a{42}; // Same with = 42; Syntax
};

int main() {
    try {
        B b;
    } catch (int const e) {
        return e;
    }
}

当编译GCC(版本4.7.4,4.8.5,4.9.3,5.4.0,6.3.0)时:

$g++ -std=c++11 test.cpp -o test; ./test ; echo $?
terminate called after throwing an instance of 'int'
Aborted
134

但是当用Clang(版本4.0.0)编译时:

$clang++ -std=c++11 test.cpp -o test; ./test ; echo $?
42

哪个行为是正确的?

解决方法

这是GCC( Bug 80683)中的一个错误.

如果构造函数是try / catch子句中的第一个操作,那么编译器认为它不在其中,尽管它应该包含它.

例如,以下工作很好:

#include <iostream>

struct A {
    A(int e) { throw e; }
};

struct B {
    A a{42}; // Same with = 42; Syntax
};

int main() {
    try {
        // The following forces the compiler to put B's contructor inside the try/catch.
        std::cout << "Welcome" << std::endl; 
        B b;
    } catch (int e) {
        std::cout << "ERROR: " << e << std::endl; // This is just for debugging
    }

    return 0;
}

运行:

g++ -std=c++11 test.cpp -DNDEBUG -o test; ./test ; echo $?

输出

Welcome
ERROR: 42
0

我的猜测是,由于编译器优化,它将构造函数移动到主函数的开头.它假定struct B没有构造函数,那么它假定它不会抛出异常,因此可以将它移动到try / catch子句之外.

如果我们将struct struct的声明改为明确地使用struct A构造函数

struct B {
    B():a(42) {}
    A a;
};

那么结果将如预期的那样,我们将进入try / catch,即使删除“欢迎”打印输出

ERROR: 42
0

猜你在找的C&C++相关文章