c++ - 抛出具有对局部变量的 const 引用的异常

标签 c++ stack-unwinding

在堆栈展开期间,在异常中引用的局部变量会发生什么?考虑以下代码:

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
    }
}

最佳答案

行为与返回对堆栈上变量的引用时的行为相同:对象在您使用它之前被销毁。也就是说,在异常被捕获时,被引用的对象被销毁,所有对引用的访问都会导致未定义的行为。

标准中的相关条款是15.2 [except.ctor] paragraph 1:

As control passes from the point where an exception is thrown to a handler, destructors are invoked for all automatic objects constructed since the try block was entered. The automatic objects are destroyed in the reverse order of the completion of their construction.

关于c++ - 抛出具有对局部变量的 const 引用的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27337324/

相关文章:

c++ - 如何将圆形数组而不是常规数组传递给 OpenGL 函数?

c++ - 继承自定义TabBar和resizeEvent的实现

c++ - 这是什么意思? (int &)a

c++ - 是否可以使用模板元编程来编译时选择该类将执行的功能?

c - 在 HP-UX 和 Linux 上展开堆栈

c++ - 线程没有运行,为什么?

c++ - 有没有办法让 DisableUserModeCallbackFilter 在 Windows 10 中工作?

ruby - 如何在没有 catch/try/raise 的情况下展开(多级返回)堆栈?

c++ - 如果一个对象在本地创建并在 C++ 中作为异常抛出,那么本地对象如何在其范围之外有效,即在 catch block 中?

c++ - 在 C++98 中,如何在不展开的情况下退出进程?