【C++】C++學(xué)習(xí)筆記之四:引用、參數(shù)傳遞和返回值

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é)果:


Paste_Image.png

【結(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é)果:

Paste_Image.png

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é)果:


Paste_Image.png

可以看到形參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ù)和返回值傳遞的過程中,如果可以盡量使用引用的方式傳遞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,663評論 1 51
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 4,190評論 1 10
  • 常量與變量使用let來聲明常量,使用var來聲明變量。聲明的同時賦值的話,編譯器會自動推斷類型。值永遠(yuǎn)不會被隱式轉(zhuǎn)...
    莫_名閱讀 526評論 0 1
  • 感賞女兒今天中午還在學(xué)校吃飯,我又可以放假啦!做完家務(wù)去媽媽家,好久沒有去了。我想幫媽媽做點家務(wù),媽媽說:不用不用...
    勿忘我瑤閱讀 117評論 5 3
  • 設(shè)置公私鑰 因為我已經(jīng)有了一套GitHub的公密鑰,為默認(rèn)的id_rsa,所以還需要生成GitCafe的公密鑰,為...
    漫談理想李叔叔閱讀 424評論 0 1

友情鏈接更多精彩內(nèi)容