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

Col*_*nee 1 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;
}
Run Code Online (Sandbox Code Playgroud)

是否有可能导致e.what包含垃圾,但是e.在哪里保持完整?例如:
e.where是"123"
e.get()返回大量垃圾数据,直到碰巧遇到空字节.

AnT*_*AnT 6

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

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

throw;
Run Code Online (Sandbox Code Playgroud)

代替

throw e;
Run Code Online (Sandbox Code Playgroud)

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

但是,你的代码是不正确的

e.app("1"); 
Run Code Online (Sandbox Code Playgroud)

调用(和其他调用app),因为参数是非const引用.将app声明更改为

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

为了编译.

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

  • 它可能值得一提,你应该通过引用来避免对象切片 (4认同)