c++引用總結

1、變量的引用:html

引用:就是某一變量(目標)的一個別名,對引用的操做與對變量直接操做徹底同樣。ios

引用的聲明方法:類型標識符 &引用名=目標變量名;c++

 例:char ch; 安全

       char &rp=ch;函數

 1)引用僅是變量的別名,而不是實實在在地定義了一個變量,所以引用自己並不佔用內存,而是和目標變量共同指向目標變量的內存地址.spa

 2)表達式中的取地址符&再也不是取變量的地址,而是用來表示該變量是引用類型的變量。指針

 3)定義一個引用時,必須對其初始化。htm

 示例代碼:對象

#include <stdio.h>
#include <iostream>
using namespace std;

//c++中的引用實例
void fun(int &x){
     printf("形式參數的值爲:%d\n",x);
     printf("形式參數的地址爲:%d\n",&x);
     x+=10;
}
void fun2(int *num){
  printf("形式參數的值爲:%d\n",*num);
  printf("形式參數的地址值爲:%d\n",num); //2686724
  printf("形式參數的地址爲:%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.引用和目標變量的地址是同樣的,對引用的修改就是對目標變量的修改。blog

                         2. 然後邊用指針做爲函數參數,把地址傳過去,指針變量的地址是2686608,而它的值是2686696(在指針的地址上存的值),2686696這個地址指向的值是3,也就是num的值。

                         3.指針變量是有本身的值的(2686608),和num的地址(2686696)不同,而引用的地址是和變量的值同樣的。

2、引用的應用

一、引用做爲參數

  引用的一個重要做用就是做爲函數的參數。之前的C語言中函數參數傳遞是值傳遞,若是有大塊數據做爲參數傳遞的時候,採用的方案每每是指針,由於這樣能夠避免將整塊數據所有壓棧,能夠提升程序的效率。可是如今(C++中)又增長了一種一樣有效率的選擇(在某些特殊狀況下又是必須的選擇),就是引用。

     (1)使用引用傳遞函數的參數,在內存中並無產生實參的副本,它是直接對實參操做;而使用通常變量傳遞函數的參數,當發生函數調用時,須要給形參分配存儲單元,形參變量是實參變量的副本;若是傳遞的是對象,還將調用拷貝構造函數。所以,當參數傳遞的數據較大時,用引用比用通常變量傳遞參數的效率和所佔空間都好。

  (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;//
}

  

     三、引用做爲返回值

  要以引用返回函數值,則函數定義時要按如下格式:

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

    {  函數體  }

  說明:

  (1)以引用返回函數值,定義函數時須要在函數名前加&

  (2)用引用返回一個函數值的最大好處是,在內存中不產生被返回值的副本。

 如下程序中定義了一個普通的函數fn1(它用返回值的方法返回函數值),另一個函數fn2,它以引用的方法返回函數值。

#include <iostream>
using namespace std;
 float temp;//定義全局變量temp
 float fn1(float r);//聲明函數fn1
 float &fn2(float r);//聲明函數fn2 r
 float fn1(float r){//定義函數fn1,它以返回值的方法返回函數值
    temp=(float)(r*r*3.14);
    return temp;
  }

  float &fn2(float r){//定義函數fn2,它以引用方式返回函數值
     temp=(float)(r*r*3.14);
     return temp;
 }

 int main(){
     float e=10.0;
     float a=fn1(10.0);//第1種狀況,系統生成要返回值的副本(即臨時變量)
    // float &b=fn1(10.0); //第2種狀況,可能會出錯(不一樣 C++系統有不一樣規定)
   /*error: invalid initialization of non-const reference of type 'float&' from an rvalue of type 'float'
   */
     //不能從被調函數中返回一個臨時變量或局部變量的引用
     float c=fn2(10.0);//第3種狀況,系統不生成返回值的副本
     //能夠從被調函數中返回一個全局變量的引用
     float &d=fn2(10.0); //第4種狀況,系統不生成返回值的副本
     e=d;

     cout<<"a="<<a<<",c="<<c<<",d="<<d<<",e="<<e<<endl;
     //a=314,c=314,d=314
     return 0;
   }

  引用做爲返回值,必須遵照如下規則:

  (1)不能返回局部變量的引用。這條能夠參照Effective C++[1]的Item 31。主要緣由是局部變量會在函數返回後被銷燬,所以被返回的引用就成爲了"無所指"的引用,程序會進入未知狀態。如【例5】中的第2種狀況出現編譯錯誤。

  (2)不能返回函數內部new分配的內存的引用。這條能夠參照Effective C++[1]的Item 31。雖然不存在局部變量的被動銷燬問題,可對於這種狀況(返回函數內部new分配內存的引用),又面臨其它尷尬局面。例如,被函數返回的引用只是做爲一個臨時變量出現,而沒有被賦予一個實際的變量,那麼這個引用所指向的空間(由new分配)就沒法釋放,形成memory leak。

  (3)能夠返回類成員的引用,但最好是const。這條原則能夠參照Effective C++[1]的Item 30。主要緣由是當對象的屬性是與某種業務規則(business rule)相關聯的時候,其賦值經常與某些其它屬性或者對象的狀態有關,所以有必要將賦值操做封裝在一個業務規則當中。若是其它對象能夠得到該屬性的很是量引用(或指針),那麼對該屬性的單純賦值就會破壞業務規則的完整性。

  (4)引用與一些操做符的重載:流操做符<<和>>,這兩個操做符經常但願被連續使用,例如:cout << \"hello\" << endl; 所以這兩個操做符的返回值應該是一個仍然支持這兩個操做符的流引用。可選的其它方案包括:返回一個流對象和返回一個流對象指針。可是對於返回一個流對象,程序必須從新(拷貝)構造一個新的流對象,也就是說,連續的兩個<<操做符其實是針對不一樣對象的!這沒法讓人接受。對於返回一個流指針則不能連續使用<<操做符。所以,返回一個流對象引用是唯一選擇。這個惟一選擇很關鍵,它說明了引用的重要性以及無可替代性,也許這就是C++語言中引入引用這個概念的緣由吧。 賦值操做符=。這個操做符象流操做符同樣,是能夠連續使用的,例如:x = j = 10;或者(x=10)=100;賦值操做符的返回值必須是一個左值,以即可以被繼續賦值。所以引用成了這個操做符的唯一返回值選擇。

四、引用和多態

  引用是除指針外另外一個能夠產生多態效果的手段。這意味着,一個基類的引用能夠指向它的派生類實例。

  【例7】:

    class  A;

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

    B  b;

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

  Ref 只能用來訪問派生類對象中從基類繼承下來的成員,是基類引用指向派生類。若是A類中定義有虛函數,而且在B類中重寫了這個虛函數,就能夠經過Ref產生多態效果。

 

  引用總結

  (1)在引用的使用中,單純給某個變量取個別名是毫無心義的,引用的目的主要用於在函數參數傳遞中,解決大塊數據或對象的傳遞效率和空間不如意的問題。

  (2)用引用傳遞函數的參數,能保證參數傳遞中不產生副本,提升傳遞的效率,且經過const的使用,保證了引用傳遞的安全性。

  (3)引用與指針的區別是,指針經過某個指針變量指向一個對象後,對它所指向的變量間接操做。程序中使用指針,程序的可讀性差;而引用自己就是目標變量的別名,對引用的操做就是對目標變量的操做。

  (4)使用引用的時機。流操做符<<和>>、賦值操做符=的返回值、拷貝構造函數的參數、賦值操做符=的參數、其它狀況都推薦使用引用。

        寫得真好:http://www.cnblogs.com/gw811/archive/2012/10/20/2732687.html

       保存,防止遺忘

相關文章
相關標籤/搜索