2010-02-16 34 views
1

通过非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.where保持完好?例如:
e.where是“123”
e.get()返回大量垃圾数据,直到碰巧碰到空字节为止。

+0

无法重现。也不会用app()中的非const引用进行编译。无论如何,你不会抛出一个引用,你会抛出一个副本。 – UncleBens 2010-02-16 17:04:51

+0

这并不意味着编译。该代码只是说明我指的是什么。我问是否可能导致e.get()包含垃圾数据,而不是如果它编译和工作。 – 2010-02-16 17:07:17

+0

鉴于这不是真正的代码,如果需要复制构造函数,e.get()不会返回垃圾。 – 2010-02-16 17:47:59

回答

6

有没有这样的事情,“引用引用”。这根本不可能。这没有语法。每次尝试“引用引用”时,都会引用被引用对象的副本。不用说,没有任何尝试在代码中引用参考。

这是可能的捕获以前引发的异常(甚至通过非const的),并通过它修改临时异常对象。它会工作。实际上,您可以重新抛出现有修改的现有的例外对象,而不是创建新的之一。即你可以做的

throw; 

代替

throw e; 

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

然而,形成不良的

e.app("1"); 

调用(和其他调用app),因为该参数是非常量引用代码。将app声明更改为

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

要编译。

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

+4

它可能值得一提的是,你应该通过参考避免物体切片 – 2010-02-16 17:26:44