2013-03-14 130 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