2012-03-22 32 views
1
#include <iostream> 
using namespace std; 

int main (int argc, char* const argv[]) { 
    int a = 20; 
    cout<<"address of a is "<<&a<<endl; 
    try{ 
     throw a; 
    } 
    catch (int& z) { 
      cout<<"address of z is "<<&z<<endl; 
    } 
    return 0; 
} 

a的地址與z的地址不同。這意味着引用在try catch中不起作用。如果沒有,那爲什麼編譯器不會產生任何錯誤?上面的代碼是什麼意思?參考不按預期在嘗試捕獲中工作

+4

**當您_throw_時複製** **。 – 2012-03-22 12:46:18

+0

@Adriano這意味着引用失去了它們在上述情況下使用的含義嗎? – niting112 2012-03-22 12:48:00

+0

我想這只是一個例子(所以我不會問你爲什麼抓到一個int的引用)。引用不會失去它們的含義,但是當您使用_value類型_(因爲我們的.NET朋友會調用它們),您會傳遞_throw_原始值的副本。 – 2012-03-22 12:55:27

回答

2

我想我的評論不是很清楚,所以我寫了一些答案。

當你拋出這個異常時,你可以用值把它扔出。這意味着它將被複制(無論它是基本類型還是複製對象都無關緊要)。當然,當一個對象被複制時,它的內存位置會發生變化(這是一個新的對象)。爲什麼這個?因爲異常可以展開堆棧以找到適當的catch塊。如果你通過引用丟棄東西可能得到的是垃圾(因爲當一個變量超出範圍時它將被銷燬)。我說可能,因爲實際上編譯器不允許引用引用,並且您將始終有一個副本。

如果你的異常對象真的很大,你可以考慮用new分配對象,然後拋出它的指針。但有人必須釋放它。你準備好冒險嗎?看一下(例如)在MFC上的CException實現和它的Delete()方法(它們試圖使這一點變得簡單,但我對此並不滿意)。

也許你想知道爲什麼如果你必須拋出你的價值,你通過參考。首先,因爲它是如何設計使用的std::exception(嘗試調用what()方法異常捕獲)。其次,因爲它允許編譯器執行一些優化(此外,即使不使用std :: exception,也不會創建該對象的無用副本)。

3

當您拋出任何類型的對象時,標準允許編譯器根據需要多次複製對象。因此,在catch區塊中,您可能無法獲得您投擲的原始對象,而是可能是其他對象,即原始對象的副本或原始對象副本的副本副本,等等。