有關C 引用操作的學習記錄

2021-10-25 08:50:36 字數 3730 閱讀 5945

鑑於本人學完就忘的特殊體質,決定把一些有意義的知識進行簡單的記錄。

在本篇中,重點介紹c++關於引用的相關知識。

這裡我們綜合對比三種函式引數設定方式,分別為:

所用**如下:

// arrayone.cpp -- small arrays of integers

#include

using

namespace std;

//值傳遞

void

swap01

(int a,

int b)

//位址傳遞

void

swap02

(int

*a,int

*b)//引用傳遞

void

swap03

(int

&a,int

&b)int

main()

引用可以理解為,為變數起乙個別名,別名和原名指向同乙個記憶體空間,從而對二者的操作完全等價。

典型的引用初始化如下:

int a =10;

int&b = a;

這樣,a與b完全等價。

在**中,我們使用了交換兩個變數的值來觀察函式呼叫效果。

其中,值傳遞只改變了形參,位址和引用傳遞均改變了實參,所以在主函式中列印a和b的值,就會出現交換的效果。

對比位址傳遞和引用傳遞,引用傳遞只需要在函式定義時採用對變數加乙個&符號構成引用傳遞,就可以實現和位址傳遞相同的功能,相比位址傳遞反覆的解引用和複雜的定義,要簡便很多。

函式執行效果如下:

這裡主要有兩個主要的關注點:

不要返回區域性變數的引用

函式的呼叫可以作為左值

廢話不多說,直接上**!

// arrayone.cpp -- small arrays of integers

#include

using

namespace std;

//引用做函式的返回值

//1.不要返回區域性變數的引用

int&

test01()

//這裡是用引用的方式做返回值定義函式

//2.函式的呼叫可以作為左值

int&

test02()

//這裡是用引用的方式做返回值定義函式

intmain()

對於第一點,不要返回區域性變數做引用值,可以參考子函式test01(),這裡的函式定義方式是把引用作為函式返回值,即可用於乙個引用(別名)賦給這個返回的變數。

由於這個操作是把乙個變數起乙個別名,所以原名不能是區域性變數,因為它存在於棧區,函式呼叫結束就被釋放掉了,所以test01()中的返回是非法操作。

對於第二點,對於返回引用的函式,函式的呼叫可以作為左值,觀察子函式test02(),其變化之處在於定義的變數是乙個靜態變數,靜態變數存在於程式的全域性區,是在程式結束時釋放,所以在程式生命週期中一直存在,可以作為函式返回值。

這裡我們用乙個引用ref作為a的別名。

所謂函式呼叫可以作為左值,可以這樣理解,這裡就是靜態變數a賦值為1000,證明方式為輸出ref(a的別名),可以看出,ref已經變成了1000。

函式執行結果如下:

另外,a實際上不能拿到子函式之外,例如這樣就會報錯:

test02()

=1000

;//這裡返回了a的引用,相當於就是a,ref是a的別名

cout <<

"a = "

<< a << endl;

//不能這麼使用

// arrayone.cpp -- small arrays of integers

#include

using

namespace std;

//引用的本質

int ref =0;

//自己沒事找事看看會出現什麼現象

//發現是引用,轉換為 int* const ref = &a;

void

func

(int

&ref)

intmain()

簡單介紹一下**:

從主函式定義a開始(先忽略其他的顯示),當我們建立ref引用時,編譯器將該**:

int

&ref = a;

識別為指標常量的初始化**:

int

*const ref =

&a;

所謂指標常量,就是定義了乙個指向位址固定,指向位址所在記憶體的值可以變化的指標,但是由於c++自動識別了引用,所以能夠在一定程度上降低**的輸入複雜度(肯定還有別的作用)。

之後凡是用到引用ref時,系統均自動識別為:

ref =10;

//引用的用法

*ref =10;

//編譯器識別到的

這樣我們就對引用有了更加深入的理解。

對於建立的子函式,本身沒有引起我的太大興趣,僅僅是引用作為函式引數進行傳遞,但對於程式執行產什麼了一些疑問:

如果有乙個同名的全域性變數,反覆定義和使用引用,會有什麼效果?

於是筆者建立了乙個名為ref的全域性變數,具體程式執行結果如下:

由此可見,在定義ref引用前,程式輸出全域性變數定義的資料。

在定義ref引用後,似乎覆蓋了ref這個全域性變數,之後的操作一直是作為引用了。

具體是什麼原因有待**???

引用作為一種「起別名」的方式,如果我們不希望這個別名不能改變原名的數值,應當怎麼做呢?

這裡就要用到常量引用了。

先說一下定義常量引用的方法,**如下:

//int &ref = 10;//非法引用,引用要引向合法的記憶體空間

//該行程式相當於:int temp = 10; const int &ref = temp;

intconst

&ref =10;

//沒有原名(一般不這麼用)

第一行展示了錯誤的定義方式,因為沒有給引用合法的記憶體空間(找不到記憶體)。

第三行展示了正確的定義方式,可以看到,它相當於:

int temp =10;

const

int&ref = temp;

不過這個temp並不顯示在程式中(不存在),是編譯器內部完成的等效動作。

至於常量引用,實際上一般用於函式呼叫,從而防止子函式修改實參,錯誤**如下:

void

showvalue

(const

int&temp)

這裡,形參設定為了常量引用,所以在子函式中不可以修改其數值,否則會報錯。

以上就是關於引用的簡單總結,後續會繼續補充der!

有關物件引用的淺學習

就不講什麼堆啊棧啊什麼的了,首先把基本資料型別和非基本資料型別區分開,這裡叫引用物件把。test public void test03 public people update object b,people p 輸出結果 1.update before p1people 2.update in p...

Python有關模組學習記錄

首先安裝搭建好jupyter notebook,執行成功後的截圖如下 安裝使用步驟 ps 確定python安裝路徑和安裝路徑裡面scripts資料夾路徑已經配置到環境變數中去,即pip所在路徑已經配置到環境變數中去 以下說明是在windows環境下 安裝 pip install jupyter no...

有關軟引用,弱引用,虛引用的問題

public class bitmapcache private bitmapcache 取得快取器例項 public static bitmapcache getinstance return cache 以軟引用的方式對乙個bitmap物件的例項進行引用並儲存該引用 private void a...