在堆栈展开期间局部变量会发生什么,在异常中引用?请考虑以下代码:
class bar;
class my_error
{
public:
my_error(const bar& bar) : _bar(bar) {}
const bar& get_bar() const { return _bar; }
private:
const bar& _bar;
}
...
bar some_local_object(...);
if (!foo()) {
throw my_error(some_local_object);
}
...
try {
g();
} catch (my_error& e) {
e.get_bar()
...
}
some_local_object 会发生什么?在堆栈展开期间是否应该销毁它?使用它是否安全,如示例所示?
其他问题
如前所述,此代码会导致未定义的行为。我的第二个问题是:
如果我既不允许传递对本地对象的引用也不应该尝试复制它,因为在极少数情况下它可能导致bad_alloc(这就是为什么,我猜,gcc标准库没有有意义的错误消息,即map.at抛出what()返回" map.at")的异常,那么传递附加信息的好策略是什么?请注意,即使连接多个字符串,在构造错误消息期间理论上也可能导致bad_alloc。即:
void do_something(const key& k, ....)
{
...
if (!foo(k)) {
std::ostringstream os;
os << "Key " << k << " not found"; // could throw bad_alloc
throw std::runtime_error(os.str());
}
// another approcach
if (!foo(k)) {
throw key_not_found(k); // also bad, because exception could outlive k
}
}
答案 0 :(得分:4)
行为与返回对堆栈上的变量的引用时的行为相同:在您使用它之前,对象将被销毁。也就是说,在捕获异常时,引用的对象将被销毁,并且对引用的所有访问都会导致未定义的行为。
标准中的相关条款是15.2 [except.ctor]第1段:
当控件从抛出异常的位置传递到处理程序时,将为输入try块后构造的所有自动对象调用析构函数。自动对象按照完成构造的相反顺序销毁。
答案 1 :(得分:3)
在堆栈展开期间销毁本地对象。然后该引用变为无效,悬空引用。这意味着检查异常对象以使用引用,将具有未定义的行为。