靈活而奇特的C 語言特性 引用(上)

2021-07-25 01:11:59 字數 3533 閱讀 8777

學習了博主的《漫談繼承技術》系列博文之後,相信大家都有所收穫吧!這次博主將和大家一起**《靈活而奇特的c++語言特性》,主要包括引用、常量(const)、常量表示式(constexpr)、靜態(static)、外部(expert)、型別定義(typedef)、型別別名(aliases)、型別轉換、作用域解析、統一初始化、顯示轉換運算子、特性(attribute)、使用者自定義文字、標頭檔案、可變長度引數列表和預處理器巨集。儘管這個知識清單顯得有點凌亂,但是這些話題都是博主經過精心挑選,是容易混淆的語言特性。本篇我們來學習一下引用,增進大家對《靈活而奇特的c++語言特性》的理解。

在c++中,引用是變數的別名。所有對引用的修改都會改變被引用的變數的值。可以將引用當作**指標,這個「指標」沒有取變數位址和解除引用的麻煩。說到引用,那咱們就先來談談的引用的特性:

①宣告乙個引用時,必須同時對它進行初始化,使它指向乙個已存在的物件。

②一旦乙個引用被初始化後,就不能改為指向其他物件。也就是引用天生就是常量,不能改變自己,但是可以改變它所引用的物件。

③ const修飾的引用可以引用常量或表示式,但是不能修改它所引用的物件的值。

④假設t是資料型別。t &型別的引用或t型別的變數既可以用來初始化constt &型別的引用,也可以用來初始化t &型別的引用。const t型別的變數或const t &型別的引用則只能用來初始化const t &型別的引用,除非進行強制型別轉換。

可能對於初學者來說上面的陳述有些抽象,那咱們舉個栗子吧。

#include

using

namespacestd;

int main(int

argc,char**argv)

程式執行結果:

根據上面**所舉的栗子以及程式執行結果,相信大家對引用的特性已經掌握的差不多啦。我們再來**一下陣列引用和引用陣列。

陣列引用

咱們先來一起使用一下陣列引用,了解一下它的一些特性。

#include

using

namespacestd;

int main(int

argc,char**argv) ;

//nrarray:

陣列引用,它的

size

的大小必須和引用的物件陣列的大小儲存一致,否則編譯出錯。

int(&nrarray)[size]= narray;

//給陣列元素賦值為

1~10

inti = 0;

for(auto&var : nrarray)

//通過引用輸出陣列中各元素的值

cout<

cout<

<< endl;

//通過陣列輸出陣列中各元素的值

cout<

cout<

<< endl;

return0; }

程式執行結果:

陣列引用可以完全當作陣列來看,它滿足陣列的所有性質:

①陣列名代表整個陣列空間

②陣列名是陣列首元素的位址

③陣列名是常量,不能更改

結合上面的程式,相信大家已經理解了陣列引用的概念以及用法。聰明的小夥伴可能會問:「我們在學習指標的時候有陣列指標和指標陣列,那麼模擬一下,既然有陣列引用,那麼有沒有引用陣列呢?」。不過,我只能說有這種模擬的思想是好的,c++暫不支援引用陣列的語法。可能有的小夥伴會覺得博主在欺騙他/她,那咱們寫個簡單的程式試一試吧!

#include

using

namespacestd;

int main(int

argc,char**argv) ;

return0; }

編譯器會提示一下錯誤:

其實引用是指標的封裝形式,至少你可以這樣去理解,引用的內部實現和指標一樣,任何使用引用的地方都可以用指標來代替,它們的彙編**完全一樣。只是我們在使用指標的時候容易犯錯而造成記憶體洩露和懸掛指標的問題,然而引用就不會了出現這些錯誤,不可能存在無效引用,也不需要顯式地解除引用。可能有小夥伴正在懷疑博主剛才說的話:「使用引用的地方都可以用指標來代替,並且它們的彙編**完全一樣」。咱們舉個簡單的栗子吧。

#include

using

namespacestd;

int main(int

argc,char**argv)

上面語句的彙編**如下:

看,博主沒有忽悠你吧!既然我們已經學了指標和引用,那它們之間有什麼區別呢?下面我們一起來總結下指標與引用之間的區別吧。

①指標變數可以更改指向,而引用一旦初始化之後就不能更改其指向。

②指標變數自增自減是位址在改變,這個涉及到步長的概念,步長與物件的型別有關,而引用變數自增自減則是將引用空間裡的值加1。

③指標變數可以不初始化(為了安全,建議定義時初始化),但是引用變數必須初始化。

④sizeof(指標)在32位作業系統上永遠為4,在32位作業系統上永遠為8,而sizeof(引用)則是引用空間的大小。

⑤當指標作為函式引數時,不用指定陣列的長度,但是引用必須指定長度。

如:voidfun1(int *nptr);//不用指定長度

void fun2(int(&nrarray)[size]);//必須指定長度,且長度必須和實參陣列的長度儲存一致

了這麼多引用的語法特性,那麼我們在寫程式的時候,都在什麼時候使用引用呢?引用可以作為類的資料成員、函式的引數以及函式的返回值。使用引用主要是為了效率和正確性。效率體現在複製較大物件或者結構需要較長的時間。按引用傳遞只是把指向物件或結構的「指標」傳遞給函式。正確性體現在並非所有物件都允許按值傳遞,即使允許按值傳遞的物件,也可能不支援正確的深度複製(deep coping)。為了支援深度複製,動態分配記憶體的物件必須提供自定義的複製建構函式和賦值運算子過載函式。

最後提醒大家:無法宣告引用的引用,或者指向引用的指標。博主這裡偷個懶,就不給大家舉例子啦。

相信你已經深入理解了引用的概念,並能很好的使用它。然而我們還有乙個更好玩東西:右值引用和移動語義。限於篇幅,我就不在這裡給 大家介紹右值引用和移動語義相關的知識了,我會在《靈活而奇特的c++語言特性——引用(下)》中給大家一起**。

靈活而奇特的C 語言特性 const(一)

學習了博主的 漫談繼承技術 系列博文之後,相信大家都有所收穫吧!這次博主將和大家一起 靈活而奇特的c 語言特性 主要包括引用 常量 const 常量表示式 constexpr 靜態 static 外部 expert 型別定義 typedef 型別別名 aliases 型別轉換 作用域解析 統一初始化...

靈活而奇特的C 語言特性 const(二)

學習了博主的 漫談繼承技術 系列博文之後,相信大家都有所收穫吧!這次博主將和大家一起 靈活而奇特的c 語言特性 主要包括引用 常量 const 常量表示式 constexpr 靜態 static 外部 expert 型別定義 typedef 型別別名 aliases 型別轉換 作用域解析 統一初始化...

靈活而奇特的C 語言特性 作用域解析(二)

學習了博主的 漫談繼承技術 系列博文之後,相信大家都有所收穫吧!這次博主將和大家一起 靈活而奇特的c 語言特性 主要包括引用 常量 const 常量表示式 constexpr 靜態 static 外部 expert 型別定義 typedef 型別別名 aliases 型別轉換 作用域解析 統一初始化...