色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

Hi,歡迎來到嵌入式培訓高端品牌 - 華清遠見教育科技集團<北京總部官網>,專注嵌入式工程師培養15年!
當前位置: > 華清遠見教育科技集團 > 嵌入式學習 > 講師博文 > 淺談引用
淺談引用
時間:2016-12-30作者:華清遠見

引用是C++引入的新語言特性,是C++常用的一個重要內容之一。在網上查了些資料后,在這我希望能用過一些簡單的應用來對引用進行分析。

引用的定義:

引用就是某一變量(目標)的一個別名,對引用的操作與對變量直接操作完全一樣。

引用的聲明:

類型標示符 &引用名=目標變量名

例如: 
        int a;
        int &b=a;

在這里定義了b為a的引用,通過這樣的引用,a和b表示同一對象。在這要特別的強調的是引用并不產生對象的副本,僅僅是對象的同義詞。&不是求址運算,只是一個標識符,表示定義的是一個類型標識符型的一個變量的引用。

引用的規則: 
        (1)引用被創建的同時必須被初始化(指針則可以在任何時候被初始化)。 
        (2)不能有NULL引用,引用必須與合法的存儲單元關聯(指針則可以是NULL)。 
        (3)一旦引用被初始化,就不能改變引用的關系(指針則可以隨時改變所指的對象)。 
        (4)聲明一個引用,不是定義一個變量,它只表示該引用名是目標變量的一個別名,所以它本身不是一種數據結構,因此引用本身不占存儲單元,系統也不給引用分配存儲單元。所以對引用求地址,就是對目標變量求地址。 
        (5)不能建立數組的引用。因為數組是一個由若干元素組成的集合,所以沒有辦法建立一個數組的別名。

引用的主要功能: 
        (1)傳遞函數的參數

與C語言不同,C++語言中,函數的參數和返回值的傳遞方式除了有值傳遞、指針傳遞還有引用傳遞。在C語言中如果有大塊數據作為參數傳遞的時候,采用的方案往往是指針,因為這樣可以避免將整塊數據全部壓棧,從而提高效率。而在C++中,它提供了一種提高程序效率的方法,就是引用。

void swap(int *p,int *q)
        {
                int temp;
                temp = *p;
                *p=*q;
                *q=temp;
        }

在C++中我們就可以改善我們的程序,寫成:

void swap(int &p,int &q)
        {
                int temp;
                temp = p;
                p=q;
                q=temp;
        }

這個時候我們寫主函數的時候就不用再寫成swap(&a,&b)直接寫成swap(a,b)。

從例子中我們可以看出:

(1)傳遞引用給函數與傳遞指針的效果是一樣的。這時,被調函數的形參就成為原來主調函數中的實參變量或對象的一個別名來使用,所以在被調函數中對形參變量的操作就是對其相應的目標對象(在主調函數中)的操作。

(2)使用引用傳遞函數的參數,在內存中并沒有產生實參的副本,它是直接對實參操作;而使用一般變量傳遞函數的參數,當發生函數調用時,需要給形參分配存儲單元,形參變量是實參變量的副本;如果傳遞的是對象,還將調用拷貝構造函數。因此,當參數傳遞的數據較大時,用引用比用一般變量傳遞參數的效率和所占空間都好。

(3)使用指針作為函數的參數雖然也能達到與使用引用的效果,但是,在被調函數中同樣要給形參分配存儲單元,且需要重復使用"*指針變量名"的形式進行運算,這很容易產生錯誤且程序的閱讀性較差;另一方面,在主調函數的調用點處,必須用變量的地址作為實參。而引用更容易使用,更清晰。

如果既要利用引用提高程序的效率,又要保護傳遞給函數的數據不在函數中被改變,就應使用常引用。

在這就得弄明白c++中引用和指針的區別:

(a)非空區別。在任何情況下都不能使用指向空值的引用。一個引用必須總是指向某些對象。因此如果你使用一個變量并讓他指向一個對象,但是該變量在某些時候也可能不指向任何對象,這是你應該把變量聲明為指針,因為這樣你可以賦予空值給該變量。相反,如果變量肯定指向一個對象,例如你的設計不允許變量為空,這時你就可以把變量聲明為引用。不存在指向空值得引用這個事實意味著使用引用的代碼效率比使用指針要高。

(b)合法性區別。在使用引用之前不需要測試它的合法性。相反,指針則應該總是被測試,防止其為空。

(c)可修改區別。指針與引用的另一個重要的不同是指針可以被重新賦值以指向另一個不同的對象。但是引用則是總是指向在初始化時被指定的對象,以后不能改變,但是指定的對象其內容可以改變。

(d)應用區別。總的來說,在以下情況下你應該使用指針:一是你考慮到存在不指向任何對象對象的可能(在這種情況下,你能夠設置指針為空),二是你需要能夠在不同的時刻指向不同的對象(在這種情況下,你能改變指針的指向)。如果總是指向一個對象并且一旦指向一個對象后就不會改變指向,那么你應該使用引用。

(2)返回值。

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

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

{函數體}

看下面這個程序:

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

#include <iostream.h>
        float temp; //定義全局變量temp
        float fn1(float r); //聲明函數fn1
        float &fn2(float r); //聲明函數fn2
        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; 
        } 
        void main() //主函數 
        { 
                  float a=fn1(10.0); //第1種情況,系統生成要返回值的副本(即臨時變量)
                  float &b=fn1(10.0); //第2種情況,可能會出錯(不同 C++系統有不同規定),不能從被調函數中返回一個臨時變量或局部變量的引用 
                  float c=fn2(10.0); //第3種情況,系統不生成返回值的副本,可以從被調函數中返回一個全局變量的引用 
                  float &d=fn2(10.0); //第4種情況,系統不生成返回值的副本,可以從被調函數中返回一個全局變量的引用 
                  cout<<a<<c<<d; 
        }

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

(1)不能返回局部變量的引用。

例如:float &b=fn1(10.0); 主要原因是局部變量會在函數返回后被銷毀,因此被返回的引用就成為了"無所指"的引用,程序會進入未知狀態。

(2)不能返回函數內部new分配的內存的引用。雖然不存在局部變量的被動銷毀問題,可對于這種情況(返回函數內部new分配內存的引用),又面臨其它尷尬局面。例如,被函數返回的引用只是作為一個臨時變量出現,而沒有被賦予一個實際的變量,那么這個引用所指向的空間(由new分配)就無法釋放,造成memory leak。

(3)可以返回類成員的引用,但好是const。主要原因是當對象的屬性是與某種業務規則(business rule)相關聯的時候,其賦值常常與某些其它屬性或者對象的狀態有關,因此有必要將賦值操作封裝在一個業務規則當中。如果其它對象可以獲得該屬性的非常量引用(或指針),那么對該屬性的單純賦值就會破壞業務規則的完整性。

(4)引用與一些操作符的重載:

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

(5)在另外的一些操作符中,卻千萬不能返回引用:+-*/ 四則運算符。主要原因是這四個操作符沒有side effect,因此,它們必須構造一個對象作為返回值,可選的方案包括:返回一個對象、返回一個局部變量的引用,返回一個new分配的對象的引用、返回一個靜態對象引用。根據前面提到的引用作為返回值的三個規則,第2、3兩個方案都被否決了。靜態對象的引用又因為((a+b) == (c+d))會永遠為true而導致錯誤。所以可選的只剩下返回一個對象了。

\引用的總結

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

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

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

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

發表評論
評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
主站蜘蛛池模板: 亚洲精品国产一区二区三 | 亚洲国产人在线播放首页 | 国产又爽又猛又粗的A片 | 东京热无码一区二区三区av | 国产精品自在在线午夜精华在线 | 九色视频免费观看 | 国产午夜不卡AV免费 | 无码人妻丰满熟妇区五十路 | 久久亚洲精品国产精品 | 中文字幕高清在线免费播放 | 黑人玩弄出轨人妻松雪 | 99热这里只有精品国产免费免费 | 日本欧美国产一区二区三区 | 欧美性生活一区二区三区 | 日本一级特黄aa大片 | 美女露100%奶头无遮挡 | 亚洲国产成人精品无码区 | 国产精品草逼 | 国产一区二区色 | 已婚丰满少妇潮喷21P | 5g多人运动罗志祥免费观看影视网 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲综合天堂AV网站在线观看 | 国产成人资源 | 免费看久久妇女高潮A | 少妇性BBB搡BBB爽爽爽视频 | 人妻少妇伦在线无码 | 初尝人妻的滋味hd | 国产午夜伦鲁鲁 | 亚洲AV无码一区二区三区人 | 国产麻豆精品传媒AV国产婷婷 | 挺进邻居丰满少妇的身体 | 播放灌醉水嫩大学生国内精品 | 亚洲二区av | 国产精品岛国久久久久久 | 国内美女人妻一级毛片免费看 | 久久精品国产99国产精品澳门 | 国产小嫩模无套中出 | 一区二区乱子伦在线播放 | 1000部又爽又黄无遮挡的视频 | 无遮无挡爽爽免费视频 |