1. 引用
1.1 左值引用
我們通常提到的引用都是指“左值引用”, 其語法如下:
<類型名> & <變量名> = <變量名>;
左值引用就是alias,相當(dāng)于給對象起了個別名,當(dāng)定義引用時,編譯器會把引用型變量與它的初始值(也是個變量名)綁定在一起,使用引用型變量跟使用其初始值變量等同,同時改變。
一旦完成綁定(初始化),引用型變量會和它的初始值一直綁定在一起,因此不能將引用再重新綁定到另一個變量身上。
對于重新綁定的問題,來做個小實驗:
int main(int argc, char** argv){
int i = 10;
int ii = 12;
int &a = i;
a = ii;
cout << "a:" << a << endl
<< "i:" << i << endl
<< "ii:" << ii << endl;
return 0;
}
編譯后運行,得到如下結(jié)果:

【結(jié)論】:
由以上實驗結(jié)果可以看到,對于已經(jīng)綁定了i的引用型變量a,對其再賦值變量ii,并沒有報語法錯誤。但是,其實際的操作結(jié)果,并不像我們的本來意圖(想讓a再與ii綁定在一起),而是對本來綁定在一起的a和i變量做了一次賦值,把ii的值傳遞給了a和i兩個變量。
因此,以后在代碼中使用引用型變量時,切記,一旦綁定關(guān)系成立,不要試圖解除綁定關(guān)系。結(jié)果很可能會事與愿違。
1.2 右值引用(C++11)
我們通常所說的引用都是“左值引用”。還有一種形式的引用叫做“右值引用”,是對數(shù)值的引用。其語法如下:
<類型名> && <變量名> = <右值>;
其特點是:只能綁定到一個將要銷毀的對象上,其作用就是把右值資源“移動”到另一個對象中去。
這里暫不探討。
2. 參數(shù)傳遞
參數(shù)傳遞發(fā)生在函數(shù)調(diào)用階段,函數(shù)定義中參數(shù)列表里的參數(shù)叫做形式參數(shù),實際調(diào)用函數(shù)時傳入的參數(shù)叫做實際參數(shù)。
1.1 值傳遞(pass by value)
一般在參數(shù)傳遞的過程中,沒有特別標(biāo)注(不實用指針和引用),都是值傳遞,即在函數(shù)中發(fā)生的參數(shù)值的改變都是作用于形式參數(shù),而對實際參數(shù)沒有影響。
下面寫段代碼來觀察下值傳遞:
class varTest{
public:
static void increase(int var){
var++;
cout << "var:" << var << endl;
}
};
int main(int argc, char** argv){
int i = 10;
varTest::increase(i);
cout << "i:" << i << endl;
return 0;
}
程序編譯后運行,得到如下結(jié)果:

1.2 引用傳遞(pass by reference)
有了上面"引用綁定"和"形參實參關(guān)系"分析的基礎(chǔ),那么,函數(shù)參數(shù)以引用方式傳遞就很好理解了,就是把形參和實參綁定在一起,如果在函數(shù)體里對實參有修改,修改會真的起作用。
還是一段代碼,驗證下:
class varTest{
public:
static void increase(int &var){
var++;
cout << "var:" << var << endl;
}
};
int main(int argc, char** argv){
int i = 10;
varTest::increase(i);
cout << "i:" << i << endl;
return 0;
}
編譯運行結(jié)果:

可以看到形參var和實參i的值都改變了。
1.3 常量型引用傳遞(pass by reference to const)
引用在編譯器底層的實現(xiàn)本質(zhì)上就是一個指針,或者說跟指針的原理相同,這使它既能提高傳遞效率,同時看起來又好像是一個對象,使用起來更方便直觀。
所以現(xiàn)在一般都會建議程序員,在使用函數(shù)參數(shù)傳遞時,盡量使用引用的方式傳遞,其開銷相當(dāng)于一個4byte的指針類型的參數(shù)傳遞的開銷??梢跃徑夂瘮?shù)調(diào)用時壓棧帶來的負(fù)擔(dān)。
但有些情況下,雖然傳遞引用型參數(shù)調(diào)用函數(shù)的效率會比較高,可是調(diào)用者也許并不希望函數(shù)內(nèi)部改變引用參數(shù)的數(shù)值,這就用到了傳遞常量型引用參數(shù)。
3.返回值
2.1 臨時變量與值傳遞返回值(return by value)
臨時變量通常指在一定生存周期(scope)范圍內(nèi)的變量,其在此范圍內(nèi)分配內(nèi)存(通常是棧上的內(nèi)存),跨出生命周期,變量的內(nèi)存將被釋放,變量消失。
前面說,盡量使用引用的方式傳遞參數(shù),同樣的道理也適用函數(shù)返回值的傳遞。但并不是所有情況下都可以用引用的方式返回值。當(dāng)返回值涉及到傳遞臨時變量就必須使用值傳遞的方式。
看代碼:
inline complex operator+(const complex& c1, const complex& c2){
return complex(c1.re+c2.re, c1.im+c2.im);
}
2.2 引用傳遞返回值(return by reference)
直接看代碼:
inline complex operator+=(complex *ths, const complex & c){
ths->re += c.re;
ths->im += c.im;
return *ths;
}
2.3 返回值傳遞到常量引用(return by reference to const)
返回值傳遞到常量引用跟返回值以引用方式傳遞一樣,其實,函數(shù)開發(fā)者,不需要關(guān)注引用型返回值是不是傳遞給了常量,傳遞給常量引用是使用者的考量。其編碼方式與上面的引用傳遞返回值是一樣的。
只不過要考率的地方是在調(diào)用時,是否要使用常量引用型變量對返回值綁定的決策上。
【技巧】:參數(shù)和返回值傳遞的過程中,如果可以盡量使用引用的方式傳遞。