通过引用投掷非常设临时工

时间:2010-02-16 16:57:38

标签: c++ exception undefined-behavior

使用非const引用在try-block中抛出构造在堆栈上的对象,捕获并修改它,然后通过引用另一个catch块抛出它会有问题吗?

以下是我所指的内容的简短示例。

struct EC {
    EC(string msg) { what = msg; }
    string where;
    string what;

    void app(string& t) { where += t; }
    string get() { return what; }
};

try {
    try {
        try {
            EC error("Test");
            throw error;
        }
        catch (EC& e) {
            e.app("1");
            throw e;
        }
    }
    catch (EC& e) {
        e.app("2");
        throw e;
    }
}
catch (EC& e) {
     e.app("3");
     cout << e.where << endl;
     cout << e.get() << endl;
}

这是否有可能导致e.what包含垃圾,但是e。在哪里保持完整?例如:
e。其中是“123”
e.get()返回大量垃圾数据,直到碰到空字节为止。

1 个答案:

答案 0 :(得分:6)

没有“通过引用投掷”这样的事情。这根本不可能。这没有语法。每次尝试“抛出引用”时,实际抛出引用对象的副本。不用说,没有尝试在代码中引用引用。

可以通过引用捕获先前抛出的异常(即使是非常量异常)并通过它修改临时异常对象。它会工作。实际上,您可以重新抛出现在修改的现有异常对象,而不是创建 new 异常对象。即你可以做到

throw;

而不是

throw e;

在你的catch子句中仍然得到正确行为的代码,即原始对象(带有修改)将继续其处理程序层次结构的飞行。

但是,您的代码在

中格式不正确
e.app("1"); 

调用(以及对app的其他调用),因为该参数是非const引用。将app声明更改为

void app(const string& t) { where += t; }  // <- either this
void app(string t) { where += t; }         // <- or this

要编译。

否则,您的代码应该可以正常工作。你不应该从get()得到任何垃圾。如果这样做,那么它必须是编译器的问题,或者是您未显示的代码。