【C++語法】引用詳解

引用是什麼?

引用就是一個變量的別名數組


引用的定義語法

int b; int & a=b; 這裏代表的是a是一個指向int類型變量的引用,也就是說a是b的一個別名。ide


引用在哪些地方使用?

引用最常使用的地方是用作函數的參數函數


函數調用用引用

函數調用時使用引用的話,函數使用的就是該變量,而不是該變量的一份拷貝指針


使用引用的注意事項

  • 引用在定義或者聲明的時候就須要給他賦值
  • 引用不能做爲數組中的元素,主要緣由是引用不支持傳統意義上的複製,好比int &(a)[10]這種定義是非法的

不能創建引用數組

不能創建數組的引用是說,數組的元素不能是引用。code

兩種寫法對象

  • int (&b)[3] = a; 這是合法的,b自己是一個引用,b不是數組。b的引用是數組名a.
  • int& b[3]; 這樣b是數組,數組中元素纔是引用。這樣C++不支持,由於引用不能夠做數組中的元素。

緣由內存

主要引用不能夠做爲數組元素的緣由是它不支持傳統意義的複製。編譯器


傳統意義的複製string

int a = b;
a和b在內存中分別佔用,內容一致。
若是
int &a = b;
這種複製,內存中a並不分配新的內存。因此這不是複製

引用的內存分配問題

從C++標準上看,是不會爲引用分配內存的,但從彙編的狀況看,應該是爲引用分配了內存的,只是C++編譯器對此做了特殊處理編譯


使用引用作函數參數時有哪些特色?

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

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


使用引用做爲函數的參數與使用指針做爲函數的參數相比有哪些優勢?

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

簡要說說引用做爲函數返回值的類型的好處

格式及好處

  • 格式:類型標識符 &函數名(形參列表及類型說明){ //函數體 }

  • 好處:在內存中不產生被返回值的副本;(注意:正是由於這點緣由,因此返回一個局部變量的引用是不可取的。由於隨着該局部變量生存期的結束,相應的引用也會失效,產生runtime error!


引用做爲函數返回值的注意事項

  • 不能返回局部變量的引用。這條能夠參照Effective C++[1]的Item 31。主要緣由是局部變量會在函數返回後被銷燬,所以被返回的引用就成爲了"無所指"的引用,程序會進入未知狀態。

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

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

  • 流操做符重載返回值申明爲"引用"的做用: 流 操做符< <和> >,這兩個操做符經常但願被連續使用,例如:cout << "hello" << endl; 所以這兩個操做符的返回值應該是一個仍然支持這兩個操做符的流引用。可選的其它方案包括:返回一個流對象和返回一個流對象指針。可是對於返回 一個流對象,程序必須從新(拷貝)構造一個新的流對象,也就是說,連續的兩個<<操做符其實是針對不一樣對象的!這沒法讓人接受。對於返回一 個流指針則不能連續使用<<操做符。所以, 返回一個流對象引用是唯一選擇。這個惟一選擇很關鍵,它說明了引用的重要性以及無可替代性,也許這 就是C++語言中引入引用這個概念的緣由吧。賦值操做符=。這個操做符象流操做符同樣,是能夠連續使用的,例如:x = j = 10;或者(x=10)=100;賦值操做符的返回值必須是一個左值,以即可以被繼續賦值。所以引用成了這個操做符的唯一返回值選擇。
  • **在另外的一些操做符中,卻千萬不能返回引用:+-*/ 四則運算符**。它們不能返回引用,Effective C++[1]的Item23詳細的討論了這個問題。主要緣由是這四個操做符沒有side effect,所以,它們必須構造一個對象做爲返回值,可選的方案包括:返回一個對象、返回一個局部變量的引用,返回一個new分配的對象的引用、返回一 個靜態對象引用。根據前面提到的引用做爲返回值的三個規則,第二、3兩個方案都被否決了。靜態對象的引用又由於((a+b) == (c+d))會永遠爲true而致使錯誤。因此可選的只剩下返回一個對象了。???還不是太明白


何時須要使用「常引用」?

若是既要利用引用提升程序的效率,又要保護傳遞給函數的數據不在函數中被改變,就應使用常引用。常引用聲明方式:const 類型標識符 &引用名=目標變量名;


舉例1

定義「常引用」後,咱們不能輕易修改「常引用」的值。


舉例2

string foo();
void bar (string &s);
// 下面的表達式都將是非法的
bar(foo());// 這裏會生成一個const String類型的臨時對象,而bar函數的類型爲非const類型,因此這個調用時非法的。
bar("hello, world");

緣由在於foo( )和"hello world"串都會產生一個臨時對象,而在C++中,這些臨時對象都是const類型的。所以上面的表達式就是試圖將一個const類型的對象轉換爲非const類型,這是非法的。引用型參數應該在能被定義爲const的狀況下,儘可能定義爲const 。

相關文章
相關標籤/搜索