微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐