程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中援用(&)的用法與運用實例剖析

C++中援用(&)的用法與運用實例剖析

編輯:關於C++

C++中援用(&)的用法與運用實例剖析。本站提示廣大學習愛好者:(C++中援用(&)的用法與運用實例剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中援用(&)的用法與運用實例剖析正文


關於習氣應用C停止開辟的同伙們,在看到c++中湧現的&符號,能夠會犯含混,由於在C說話中這個符號表現了取地址符,然則在C++中它卻有著分歧的用處,控制C++的&符號,是進步代碼履行效力和加強代碼質量的一個很好的方法。

援用是C++引入的新說話特征,是C++經常使用的一個主要內容之一,准確、靈巧地應用援用,可使法式簡練、高效。我在任務中發明,很多人應用它僅僅是想固然,在某些奧妙的場所,很輕易失足,究其緣由,年夜多由於沒有弄清根源。故在本篇中我將對援用停止具體評論辯論,願望對年夜家更好地輿解和應用援用起到拋磚引玉的感化。

1、援用簡介

援用就是某一變量(目的)的一個體名,對援用的操作與對變量直接操作完整一樣。

援用的聲明辦法:類型標識符 &援用名=目的變量名;

【例1】:
int a; int &ra=a; //界說援用ra,它是變量a的援用,即別號

解釋:

(1)&在此不是求地址運算,而是起標識感化。

(2)類型標識符是指目的變量的類型。

(3)聲明援用時,必需同時對其停止初始化。

(4)援用聲明終了後,相當於目的變量名有兩個稱號,即該目的原稱號和援用名,且不克不及再把該援用名作為其他變量名的別號。

 ra=1; 等價於 a=1;

(5)聲明一個援用,不是新界說了一個變量,它只表現該援用名是目的變量名的一個體名,它自己不是一種數據類型,是以援用自己不占存儲單位,體系也不給援用分派存儲單位。故:對援用求地址,就是對目的變量求地址。&ra與&a相等。

(6)不克不及樹立數組的援用。由於數組是一個由若干個元素所構成的聚集,所以沒法樹立一個數組的別號。

2、援用運用

1、援用作為參數

援用的一個主要感化就是作為函數的參數。之前的C說話中函數參數傳遞是值傳遞,假如有年夜塊數據作為參數傳遞的時刻,采取的計劃常常是指針,由於如許可以免將整塊數據全體壓棧,可以進步法式的效力。然則如今(C++中)又增長了一種異樣有用率的選擇(在某些特別情形下又是必需的選擇),就是援用。

【例2】:

void swap(int &p1, int &p2) //此處函數的形參p1, p2都是援用
{ int p; p=p1; p1=p2; p2=p; }

為在法式中挪用該函數,則響應的主調函數的挪用點處,直接以變量作為實參停止挪用便可,而不須要實參變量有任何的特別請求。如:對應下面界說的swap函數,響應的主調函數可寫為:

main( )
{
 int a,b;
 cin>>a>>b; //輸出a,b兩變量的值
 swap(a,b); //直接以變量a和b作為實參挪用swap函數
 cout<<a<< ' ' <<b; //輸入成果
}

上述法式運轉時,假如輸出數據10 20並回車後,則輸入成果為20 10。

由【例2】可看出:

(1)傳遞援用給函數與傳遞指針的後果是一樣的。這時候,被調函數的形參就成為本來主調函數中的實參變量或對象的一個體名來應用,所以在被調函數中對形參變量的操作就是對其響應的目的對象(在主調函數中)的操作。

(2)應用援用傳遞函數的參數,在內存中並沒有發生實參的正本,它是直接對實參操作;而應用普通變量傳遞函數的參數,當產生函數挪用時,須要給形參分派存儲單位,形參變量是實參變量的正本;假如傳遞的是對象,還將挪用拷貝結構函數。是以,當參數傳遞的數據較年夜時,用援用比用普通變量傳遞參數的效力和所占空間都好。

(3)應用指針作為函數的參數固然也能到達與應用援用的後果,然則,在被調函數中異樣要給形參分派存儲單位,且須要反復應用"*指針變量名"的情勢停止運算,這很輕易發生毛病且法式的浏覽性較差;另外一方面,在主調函數的挪用點處,必需用變量的地址作為實參。而援用更輕易應用,更清楚。

假如既要應用援用進步法式的效力,又要掩護傳遞給函數的數據不在函數中被轉變,就應應用常援用。

2、常援用

常援用聲明方法:const 類型標識符 &援用名=目的變量名;

用這類方法聲明的援用,不克不及經由過程援用對目的變量的值停止修正,從而使援用的目的成為const,到達了援用的平安性。

【例3】:

int a ;
const int &ra=a;
ra=1; //毛病
a=1; //准確

這不但是讓代碼更硬朗,也有些其它方面的須要。

【例4】:假定有以下函數聲明:

string foo( );
void bar(string & s);

那末上面的表達式將長短法的:

bar(foo( ));
bar("hello world");

緣由在於foo( )和"hello world"串都邑發生一個暫時對象,而在C++中,這些暫時對象都是const類型的。是以下面的表達式就是試圖將一個const類型的對象轉換為非const類型,這長短法的。

援用型參數應當在能被界說為const的情形下,盡可能界說為const 。


3、援用作為前往值

要以援用前往函數值,則函數界說時要按以下格局:

類型標識符 &函數名(形參列表及類型解釋)
{函數體}

解釋:

(1)以援用前往函數值,界說函數時須要在函數名前加&

(2)用援用前往一個函數值的最年夜利益是,在內存中不發生被前往值的正本。

【例5】以下法式中界說了一個通俗的函數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)不克不及前往部分變量的援用。這條可以參照Effective C++[1]的Item 31。重要緣由是部分變量會在函數前往後被燒毀,是以被前往的援用就成了"無所指"的援用,法式會進入未知狀況。

(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;賦值操作符的前往值必需是一個左值,以即可以被持續賦值。是以援用成了這個操作符的唯一前往值選擇。

【例6】 測試用前往援用的函數值作為賦值表達式的左值。

#include <iostream.h>
int &put(int n);
int vals[10];
int error=-1;
void main()
{
put(0)=10; //以put(0)函數值作為左值,等價於vals[0]=10;
put(9)=20; //以put(9)函數值作為左值,等價於vals[9]=20;
cout<<vals[0];
cout<<vals[9];
}
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,是以,它們必需結構一個對象作為前往值,可選的計劃包含:前往一個對象、前往一個部分變量的援用,前往一個new分派的對象的援用、前往一個靜態對象援用。依據後面提到的援用作為前往值的三個規矩,第2、3兩個計劃都被否決了。靜態對象的援用又由於((a+b) == (c+d))會永久為true而招致毛病。所以可選的只剩下前往一個對象了。

4、援用和多態

援用是除指針外另外一個可以發生多態後果的手腕。這意味著,一個基類的援用可以指向它的派生類實例。

【例7】:

class  A;
class  B:public A{……};
B  b;
A  &Ref = b; // 用派生類對象初始化基類對象的援用

Ref 只能用來拜訪派生類對象中從基類繼續上去的成員,是基類援用指向派生類。假如A類中界說有虛函數,而且在B類中重寫了這個虛函數,便可以經由過程Ref發生多態後果。

3、援用總結

(1)在援用的應用中,純真給某個變量取個體名是毫有意義的,援用的目標重要用於在函數參數傳遞中,處理年夜塊數據或對象的傳遞效力和空間不如意的成績。

(2)用援用傳遞函數的參數,能包管參數傳遞中不發生正本,進步傳遞的效力,且經由過程const的應用,包管了援用傳遞的平安性。

(3)援用與指針的差別是,指針經由過程某個指針變量指向一個對象後,對它所指向的變量直接操作。法式中應用指針,法式的可讀性差;而援用自己就是目的變量的別號,對援用的操作就是對目的變量的操作。

(4)應用援用的機會。流操作符<<和>>、賦值操作符=的前往值、拷貝結構函數的參數、賦值操作符=的參數、其它情形都推舉應用援用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved