【C++養成計劃】不得不知的——引用(Day9)

寫在前面:大家好!我是【AI 菌】,一枚愛彈吉他的程序員。我熱愛AI、熱愛分享、熱愛開源! 這博客是我對學習的一點總結與思考。如果您也對 深度學習、機器視覺、算法、Python、C++ 感興趣,可以關注我的動態,我們一起學習,一起進步~
我的博客地址爲:【AI 菌】的博客
我的Github項目地址是:【AI 菌】的Github

前言:
對於初學編程語言的同學來說,對於引用可能比較陌生,幾乎用不到。但是在C++中,引用的地位就如同指針一樣,它是你深入瞭解編程語言的必經之路,也是你提升代碼質量的利器!那麼今天我們就來聊聊C++中的引用吧~

想快速入門指針的同學,可以戳戳這篇有趣的分享:面試官:指針都不會,我們不需要你這樣的人!

1. 什麼是引用

在講引用之前,我們得了解一個詞——別名,也可以說是曾用名。想想自己從小到大,有過多少別名?
在這裏插入圖片描述
我們以豬八戒爲例,它的別名就有很多個,比如:二師兄、悟淨、天蓬元帥、八戒等等。瞭解了別名之後,其實你對引用就有了一個初步的認識!

簡單來說,引用是變量的別名。變量,相信大家並不陌生,它是由變量名和變量值組成。那麼當我們需要給變量取一個別名時,就可以使用引用。

在聲明引用時,需要將其初始化爲一個變量。因此通過引用,我們也可以訪問該變量的數據。

在聲明引用之前,我們需要了解一個符號:引用運算符 & 。通過&可以按如下方式進行聲明:

聲明引用:
Type 變量名 = 變量值;  //1.聲明一個變量
Type& 別名 = 變量名;   //2.聲明一個引用

下面舉一個簡單的例子,來感受一下:

#include <iostream>
using namespace std; 

int main()
{
	int a = 30;
	cout<<"a = "<<a<<endl;  
	cout<<"a的內存地址是:"<<hex<<&a<<endl;
	
	int& b = a;  //聲明一個引用 ,b可作爲s的別名 
	cout<<"b = "<<dec<<b<<endl;
	cout<<"b的內存地址是:"<<hex<<&b<<endl;
	
	int& c = b;  //聲明一個引用,c可組爲b的別名 
	cout<<"c = "<<dec<<c<<endl;
	cout<<"c的內存地址是:"<<hex<<&c<<endl; 
	return 0;
}

運行結果:
在這裏插入圖片描述
從上面這個例子,我們學習到了如何聲明一個引用。更重要的是可以得出兩條結論:

  1. 對於一個變量,可以聲明多次引用;也就是說一個變量可以有多個別名,比如b、c都是a的別名。
  2. 引用不佔用額外的內存空間。它的地址和原變量的地址相同,並且引用訪問的值=原變量的值。比如a、b、c都是30,並且內存地址也相同。

注:程序中dec,是輸出十進制的一種表示方法。

2. 按引用向函數傳遞參數

相信這個時候就有些同學坐不住了:什麼?變量也需要別名?有什麼用嗎?
在這裏插入圖片描述
你別說,還真的很有用!

引用能讓你訪問相應變量所在的內存地址,這使得編寫函數時引用很有用!

想想我們剛剛得出的一條結論:引用不佔用額外的內存空間。這一點非常重要,這也是引用非常實用的原因。下面我們就來好好聊一聊:

回憶一下,在之前的【C++養成計劃】深入淺出——函數(Day6)中講過,在調用函數時,首先實參會被傳給形參,然後再被函數使用。實參傳遞給形參,實質上是一個複製的過程;那麼在這個過程中,無疑要給形參分配一個新的內存空間去存儲實參傳來的值。如果實參本身佔用大量內存的話,這時複製的內存開銷也會很大

如果能避免這些複製,那就能節省很多內存空間了。由於引用不佔用額外的內存空間,並且它能讓你訪問相應變量所在的內存地址。因此這時候按引用向函數傳遞參數就可以大顯神通了!

按引用向函數傳遞參數時,函數的聲明方式像下面這樣:

return_type func_name(type& Parameter);

由於實參是按引用傳遞的,因此實參不再是形參的拷貝,而是它的別名。下面舉一個簡單的例子:

#include <iostream>
using namespace std; 

void func(int& num)
{
	num = num*num*num;
}

int main()
{
	cout<<"請輸入一個數:";
	int num = 0;
	cin>>num;
	func(num);
	cout<<"a="<<num<<endl;
	return 0;
}

運行結果:
在這裏插入圖片描述
想想,如果我們剛學函數,看到這個輸出結果,肯定會感到很驚訝。因爲我們學過:形參在進入函數時被創建,退出函數時被銷燬。而在這個例子中,num並沒有被銷燬,併成功的輸出了正確的結果。
這是因爲,實參傳遞給形參時,是以引用的方式,而不是拷貝。所以函數在執行時,是直接對num所在的內存單元進行操作。因此即使函數結束,這個操作的結果依然存在。

3. 將關鍵字const用於引用

使用關鍵字const聲明引用時,就不能通過引用修改它指向的變量的值了。

比如下面就是一個常見的錯誤:

int a = 30;
const int& b = a; //使用const聲明一個靜態引用
1.錯誤的做法:通過靜態引用去修改變量
b = 40; //錯誤
2.正確的做法:通過原變量修改
a = 40; //正確
3.允許的做法:通過靜態引用b再聲明一個靜態的引用
const int& c = b;

當按引用向函數傳遞參數時,爲了確保被調函數不能修改調用函數中的變量,可將引用聲明爲const。
下面舉一個簡單的例子:使用const引用確保被調用函數不能修改num

#include <iostream>
using namespace std; 

void func(const int& num, int& result)
{
	result = num*num*num;
}

int main()
{
	int num = 2, output = 0;
	func(num, output);
	cout<<num<<"^3 = "<<output<<endl;
	return 0;
}

運行結果:
在這裏插入圖片描述
假如在被調用函數func()中,意外出現num=3這樣的語句時:

void func(const int& num, int& result)
{
	num = 3;
	result = num*num*num;
}

程序就會編譯不通過。這是因爲num在函數聲明時確定爲const引用,所以在被調函數中,不能直接對num進行修改。這也保證了程序的安全性。


相關文章
點擊查看【C++21天養成計劃】

由於水平有限,博客中難免會有一些錯誤,有紕漏之處懇請各位大佬不吝賜教!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章