2013-03-14 114 views
7

考慮下面的代碼C++:如何初始化一個類的引用成員變量?

#include<iostream> 

using namespace std; 

class Test { 
    int &t; 
public: 
    Test (int &x) { t = x; } 
    int getT() { return t; } 
}; 

int main() 
{ 
    int x = 20; 
    Test t1(x); 
    cout << t1.getT() << " "; 
    x = 30; 
    cout << t1.getT() << endl; 
    return 0; 
} 

是表示在使用gcc編譯

est.cpp: In constructor ‘Test::Test(int&)’: 
    est.cpp:8:5: error: uninitialized reference member ‘Test::t’ [-fpermissive] 

爲什麼不直接編譯調用構造函數下面的錯誤?

+0

雖然答案解釋瞭如何解決這個問題,但我想指出的一個根本問題是,在進入構造函數的正文之前實際發生了初始化,以確保所有成員在使用之前處於有效狀態。由於引用**必須被初始化,並且在初始化之後不能被「重定向」,所以在輸入構造函數的主體之前,它們在邏輯上需要指向實際變量。 – 2017-06-08 23:28:14

回答

18

這是因爲引用只能在初始化程序列表中初始化。使用

Test (int &x) : t(x) {} 

解釋:引用只能設置一次,發生這種情況的地方是初始化程序列表。完成後,您不能設置引用,但只能將值分配給引用的實例。你的代碼的意思是,你試圖給引用的實例分配一些東西,但引用從未初始化,因此它不引用int的任何實例,並且出現錯誤。

+0

它們也可以通過* brace-equal-initializer *進行初始化,儘管這將是一個罕見的用例 – 2017-06-08 23:15:09

2

我的編譯器生成此錯誤:

error C2758: 'Test::t' : must be initialized in constructor base/member initializer list

而這正是你必須做什麼。參考必須在初始化列表中進行初始化:

#include<iostream> 

using namespace std; 

class Test { 
    int &t; 
public: 
    Test (int &x) : t(x) { } // <-- initializer list used, empty body now 
    int getT() { return t; } 
}; 

int main() 
{ 
    int x = 20; 
    Test t1(x); 
    cout << t1.getT() << " "; 
    x = 30; 
    cout << t1.getT() << endl; 
    return 0; 
} 

說明:

如果參考不在initiliazer名單,這是幾乎不可能的,如果參考初始化編譯器來檢測。參考文獻必須被初始化。想象一下這個場景:

Test (int &x, bool b) 
{ 
    if(b) t = x; 
} 

現在,由構造函數的調用者來決定是否生成有效的代碼。那不可能。編譯器必須確保在編譯時間處初始化引用

+4

更不用說't = x'是**而不是**參考初始化。這是一項任務。對於引用,它們*非常不同:*初始化將引用綁定到對象,賦值將分配給引用綁定到的對象。 – Angew 2013-03-14 08:03:18