C++引用總結(jié)

原文地址:https://www.cnblogs.com/jycboy/p/5184638.html

一劳秋、變量的引用:


\color{red}{引用:} \color{blue}{就是某一變量(目標)的一個別名贪庙,對引用的操作與對變量直接操作完全一樣牡昆。}

\color{red}{引用的聲明方法:}
\color{blue}{類型標識符\ \&引用名=目標變量名砰诵;}

\color{green}{如下:定義引用ra雨席,它是變量a的引用菩咨,即別名。}

\color{green}{char\ ch;}

\color{green}{char\ \&rp=ch;}

  1. 引用僅是變量的別名陡厘,而不是實實在在地定義了一個變量抽米,因此引用本身并不占用內(nèi)存,而是和目標變量共同指向目標變量的內(nèi)存地址.

  2. 表達式中的取地址符&不再是取變量的地址糙置,而是用來表示該變量是引用類型的變量云茸。

  3. 定義一個引用時,必須對其初始化罢低。

\color{red}{示例代碼:}

#include <stdio.h>
#include <iostream>
using namespace std;
 
//c++中的引用實例
void fun(int &x){
     printf("形式參數(shù)的值為:%d\n",x);
     printf("形式參數(shù)的地址為:%d\n",&x);
     x+=10;
}
void fun2(int *num){
  printf("形式參數(shù)的值為:%d\n",*num);
  printf("形式參數(shù)的地址值為:%d\n",num); //2686724
  printf("形式參數(shù)的地址為:%d\n",&num);  //2686704 這個和
  *num =(*num)+10;
 
}
 
int main(void){
   int num = 4,a=3;
 
    printf("實參num的值為:%d\n",num);
    printf("實參num的地址為:%d\n",&num);//都是一樣的
    fun(num);
   cout<<"num的值為:"<<num<<endl; //14 num的值改啦
 
   fun2(&a);
   printf("實參a的值為:%d\n",a);
   printf("實參a的地址為:%d\n",&a);//
   return 0;
}



1.和是一樣的查辩,

  1. 而后邊用指針作為函數(shù)參數(shù),把地址傳過去网持,\color{red}{指針變量的地址是2686608}宜岛,而\color{blue}{它的值是2686696}(在指針的地址上存的值),2686696這個地址指向的值是3功舀,也就是num的值萍倡。

  2. \color{red}{指針變量是有自己的值的(2686608)},和\color{red}{num的地址(2686696)}不一樣辟汰,而引用的地址是和變量的值一樣的列敲。

二、引用的應(yīng)用


\color{red}{1帖汞、引用作為參數(shù)}

引用的一個重要作用就是作為函數(shù)的參數(shù)戴而。以前的C語言中函數(shù)參數(shù)傳遞是值傳遞,如果有大塊數(shù)據(jù)作為參數(shù)傳遞的時候翩蘸,采用的方案往往是指針所意,因為這樣可以避免將整塊數(shù)據(jù)全部壓棧,可以提高程序的效率。但是現(xiàn)在(C++中)又增加了一種同樣有效率的選擇(在某些特殊情況下又是必須的選擇)扶踊,就是引用泄鹏。

#include<iostream.h>
////此處函數(shù)的形參p1, p2都是引用 
void swap(int &p1,int &p2){
    int p=p1;
    p1=p2;
    p2=p;
}

  為在程序中調(diào)用該函數(shù),則相應(yīng)的主調(diào)函數(shù)的調(diào)用點處秧耗,直接以變量作為實參進行調(diào)用即可备籽,而不需要實參
變量有任何的特殊要求。如:對應(yīng)上面定義的swap函數(shù)分井,相應(yīng)的主調(diào)函數(shù)可寫為:
void main(){
    int a,b;
    cin>>a>>b;//輸入a,b兩個變量的值
    swap(a,b);//直接以a和b作為實參調(diào)用swap函數(shù)
    cout<<"a="<<a<<",b="<<b<<endl;
}

上述程序運行時车猬,如果輸入數(shù)據(jù)10 20并回車后,則輸出結(jié)果為a=20,b=10杂抽。

\color{red}{由上例可以看出:}

\color{blue}{(1)使用引用傳遞函數(shù)的參數(shù)诈唬,在內(nèi)存中并沒有產(chǎn)生實參的副本,它是直接對實參操作缩麸;}而使用一般變量傳遞函數(shù)的參數(shù)铸磅,當(dāng)發(fā)生函數(shù)調(diào)用時,需要給形參分配存儲單元杭朱,形參變量是實參變量的副本阅仔;如果傳遞的是對象,還將調(diào)用拷貝構(gòu)造函數(shù)弧械。因此八酒,當(dāng)參數(shù)傳遞的數(shù)據(jù)較大時,用引用比用一般變量傳遞參數(shù)的效率和所占空間都好刃唐。

(2)使用指針作為函數(shù)的參數(shù)雖然也能達到與使用引用的效果羞迷,但是,在被調(diào)函數(shù)中同樣要給形參分配存儲單元画饥,且需要重復(fù)使用"*指針變量名"的形式進行運算衔瓮,這很容易產(chǎn)生錯誤且程序的閱讀性較差;另一方面抖甘,在主調(diào)函數(shù)的調(diào)用點處热鞍,必須用變量的地址作為實參。而引用更容易使用衔彻,更清晰薇宠。

\color{blue}{如果既要利用引用提高程序的效率,又要保護傳遞給函數(shù)的數(shù)據(jù)不在函數(shù)中被改變艰额,就應(yīng)使用常引用澄港。}

就如同上邊的例子一樣。

\color{red}{2柄沮、常引用}

常引用聲明方式:const 類型標識符 &引用名 = 目標變量名慢睡;

用這種方式聲明的引用逐工,不能通過引用對目標變量的值進行修改,從而使引用的目標成為const,達到了引用的安全性漂辐。

#include <stdio.h>
#include <iostream>
using namespace std;
void test_const();
 
int main(void){
 
   test_const();
   return 0;
}
 
void test_const(){
   int a=1;
     int &b=a;
     b=2;
    cout<<"a="<<a<<endl;//2
    int c=1;
    const int &d=c;
  //   d=2;//編譯錯誤 error: assignment of read_only reference 'd'
    c=2;//正確
    cout<<"c="<<c<<endl;//
}

這不光是讓代碼更健壯,也有其它方面的需求棕硫。

\color{red}{假設(shè)有如下函數(shù)聲明:}

    string foo();

    void bar(string &s);

那么下面的表達式將是非法的:

    bar(foo());

    bar("hello world");

原因在于foo( )和"hello world"串都會產(chǎn)生一個臨時對象髓涯,\color{blue}{而在C++中,臨時對象都是const類型的哈扮。}因此上面的表達式就是試圖將一個const類型的對象轉(zhuǎn)換為非const類型纬纪,這是非法的。

\color{blue}{引用型參數(shù)應(yīng)該在能被定義為const的情況下滑肉,盡量定義為const 包各。}
\color{red}{3、引用作為返回值}

要以引用返回函數(shù)值靶庙,則函數(shù)定義時要按以下格式:

    類型標識符  &函數(shù)名 (形參列表及類型說明)

   ∥食{  函數(shù)體  }

說明:
(1)以引用返回函數(shù)值,定義函數(shù)時需要在函數(shù)名前加&

\color{red}{(2)用引用返回一個函數(shù)值的最大好處是六荒,在內(nèi)存中不產(chǎn)生被返回值的副本护姆。}

以下程序中定義了一個普通的函數(shù)fn1(它用返回值的方法返回函數(shù)值),另外一個函數(shù)fn2掏击,它以引用的方法返回函數(shù)值卵皂。

#include <iostream>
using namespace std;
 float temp;//定義全局變量temp
 float fn1(float r);//聲明函數(shù)fn1
 float &fn2(float r);//聲明函數(shù)fn2 r
 float fn1(float r){//定義函數(shù)fn1,它以返回值的方法返回函數(shù)值
    temp=(float)(r*r*3.14);
    return temp;
  }
 
  float &fn2(float r){//定義函數(shù)fn2砚亭,它以引用方式返回函數(shù)值
     temp=(float)(r*r*3.14);
     return temp;
 }
 
 int main(){
     float e=10.0;
     float a=fn1(10.0);//第1種情況灯变,系統(tǒng)生成要返回值的副本(即臨時變量)

/****************************************
error: invalid initialization of non-const reference of type 'float&' from an rvalue of type 'float'
****************************************/
// float &b=fn1(10.0); //第2種情況,可能會出錯(不同 C++系統(tǒng)有不同規(guī)定)

     //不能從被調(diào)函數(shù)中返回一個臨時變量或局部變量的引用
     float c=fn2(10.0);//第3種情況捅膘,系統(tǒng)不生成返回值的副本
     //可以從被調(diào)函數(shù)中返回一個全局變量的引用
     float &d=fn2(10.0); //第4種情況添祸,系統(tǒng)不生成返回值的副本
     e=d;
 
     cout<<"a="<<a<<",c="<<c<<",d="<<d<<",e="<<e<<endl;
     //a=314,c=314,d=314
     return 0;
   }

引用作為返回值,必須遵守以下規(guī)則:

(1)\color{blue}{不能返回局部變量的引用篓跛。}這條可以參照Effective C++[1]的Item 31膝捞。\color{blue}{主要原因是局部變量會在函數(shù)返回后被銷毀},因此被返回的引用就成為了"無所指"的引用愧沟,程序會進入未知狀態(tài)蔬咬。如上面中的第2種情況出現(xiàn)編譯錯誤。

(2)\color{blue}{不能返回函數(shù)內(nèi)部new分配的內(nèi)存的引用沐寺。}這條可以參照Effective C++[1]的Item 31林艘。雖然不存在局部變量的被動銷毀問題,可對于這種情況(返回函數(shù)內(nèi)部new分配內(nèi)存的引用)混坞,又面臨其它尷尬局面狐援。例如钢坦,被函數(shù)返回的引用只是作為一個臨時變量出現(xiàn),而沒有被賦予一個實際的變量啥酱,那么這個引用所指向的空間(由new分配)就無法釋放爹凹,造成memory leak。

(3)\color{blue}{可以返回類成員的引用镶殷,但最好是const禾酱。}這條原則可以參照Effective C++[1]的Item 30。主要原因是當(dāng)對象的屬性是與某種業(yè)務(wù)規(guī)則(business rule)相關(guān)聯(lián)的時候绘趋,其賦值常常與某些其它屬性或者對象的狀態(tài)有關(guān)颤陶,因此有必要將賦值操作封裝在一個業(yè)務(wù)規(guī)則當(dāng)中。如果其它對象可以獲得該屬性的非常量引用(或指針)陷遮,那么對該屬性的單純賦值就會破壞業(yè)務(wù)規(guī)則的完整性滓走。

(4)引用與一些操作符的重載:流操作符<<和>>,這兩個操作符常常希望被連續(xù)使用帽馋,例如:cout << "hello" << endl; 因此這兩個操作符的返回值應(yīng)該是一個仍然支持這兩個操作符的流引用搅方。可選的其它方案包括:返回一個流對象和返回一個流對象指針茬斧。但是對于返回一個流對象腰懂,程序必須重新(拷貝)構(gòu)造一個新的流對象,也就是說项秉,連續(xù)的兩個<<操作符實際上是針對不同對象的绣溜!這無法讓人接受娄蔼。對于返回一個流指針則不能連續(xù)使用<<操作符锚沸。因此哗蜈,返回一個流對象引用是惟一選擇距潘。這個唯一選擇很關(guān)鍵音比,它說明了引用的重要性以及無可替代性稽犁,也許這就是C++語言中引入引用這個概念的原因吧已亥。 賦值操作符=陷猫。這個操作符象流操作符一樣的妖,是可以連續(xù)使用的嫂粟,例如:x = j = 10;或者(x=10)=100;賦值操作符的返回值必須是一個左值墨缘,以便可以被繼續(xù)賦值镊讼。因此引用成了這個操作符的惟一返回值選擇蝶棋。
\color{red}{測試用返回引用的函數(shù)值作為賦值表達式的左值}

#include<iostream.h>
int &put(int n);
int vals[10];
int error=-1;
void main(){
    put(0)=10;//以put(0)函數(shù)值作為左值兼贸,等價于vals[0]=10;
    put(9)=20;//以put(9)函數(shù)值作為左值,等價于vals[9]=20; 
    cout<<vals[0]<<endl;//10
    cout<<vals[9]<<endl;//20
}
int &put(int n){
    if(n>=0 && n<=9)
        return vals[n];
    else{
        cout<<"subscript error";
        return error;
    }
}

(5)在另外的一些操作符中螺垢,卻千萬不能返回引用:+-*/ 四則運算符。它們不能返回引用讯蒲,Effective C++[1]的Item23詳細的討論了這個問題墨林。主要原因是這四個操作符沒有side effect赁酝,因此旭等,它們必須構(gòu)造一個對象作為返回值,可選的方案包括:返回一個對象搔耕、返回一個局部變量的引用,返回一個new分配的對象的引用弃榨、返回一個靜態(tài)對象引用菩收。根據(jù)前面提到的引用作為返回值的三個規(guī)則,第2娜饵、3兩個方案都被否決了。靜態(tài)對象的引用又因為((a+b) == (c+d))會永遠為true而導(dǎo)致錯誤。所以可選的只剩下返回一個對象了拳亿。

\color{red}{4、引用和多態(tài)}

\color{blue}{引用是除指針外另一個可以產(chǎn)生多態(tài)效果的手段万搔。} \color{blue}{這意味著昧谊,一個基類的引用可以指向它的派生類實例。}

【例7】:

    class  A;

    class  B:public  A{ ... ... }

    B  b;

    A  &Ref = b;//用派生類對象初始化基類對象的引用

Ref 只能用來訪問派生類對象中從基類繼承下來的成員酗捌,是基類引用指向派生類呢诬。如果A類中定義有虛函數(shù),并且在B類中重寫了這個虛函數(shù)胖缤,就可以通過Ref產(chǎn)生多態(tài)效果尚镰。

\color{blue}{引用總結(jié)}

(1)在引用的使用中,單純給某個變量取個別名是毫無意義的哪廓,\color{blue}{引用的目的主要用于在函數(shù)參數(shù)傳遞中狗唉,解決大塊數(shù)據(jù)或?qū)ο蟮膫鬟f效率和空間不如意的問題。}

(2)\color{blue}{用引用傳遞函數(shù)的參數(shù)涡真,能保證參數(shù)傳遞中不產(chǎn)生副本}分俯,\color{blue}{提高傳遞的效率肾筐,且通過const的使用,保證了引用傳遞的安全性缸剪。}

(3)\color{blue}{引用與指針的區(qū)別是吗铐,指針通過某個指針變量指向一個對象后}\color{blue}{對它所指向的變量間接操作杏节。程序中使用指針唬渗,程序的可讀性差}\color{blue}{而引用本身就是目標變量的別名奋渔,對引用的操作就是對目標變量的操作镊逝。}

(4)\color{blue}{使用引用的時機。流操作符<<和>>嫉鲸、賦值操作符=的返回值}蹋半、\color{blue}{拷貝構(gòu)造函數(shù)的參數(shù)、賦值操作符=的參數(shù)充坑、其它情況都推薦使用引用。}

參考:https://www.cnblogs.com/jycboy/p/5184638.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末染突,一起剝皮案震驚了整個濱河市捻爷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌份企,老刑警劉巖也榄,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異司志,居然都是意外死亡甜紫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門骂远,熙熙樓的掌柜王于貴愁眉苦臉地迎上來囚霸,“玉大人,你說我怎么就攤上這事激才⊥匦停” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵瘸恼,是天一觀的道長劣挫。 經(jīng)常有香客問我,道長东帅,這世上最難降的妖魔是什么压固? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮靠闭,結(jié)果婚禮上帐我,老公的妹妹穿的比我還像新娘坎炼。我一直安慰自己,他們只是感情好焚刚,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布点弯。 她就那樣靜靜地躺著,像睡著了一般矿咕。 火紅的嫁衣襯著肌膚如雪抢肛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天碳柱,我揣著相機與錄音捡絮,去河邊找鬼。 笑死莲镣,一個胖子當(dāng)著我的面吹牛福稳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瑞侮,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼的圆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了半火?” 一聲冷哼從身側(cè)響起越妈,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钮糖,沒想到半個月后梅掠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡店归,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年阎抒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片消痛。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡且叁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秩伞,到底是詐尸還是另有隱情谴古,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布稠歉,位于F島的核電站掰担,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怒炸。R本人自食惡果不足惜带饱,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸砚尽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間迂烁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工递鹉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盟步,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓躏结,卻偏偏與公主長得像却盘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子媳拴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容