2010-02-16 36 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