目錄
引用:
注意:
左值引用和右值引用:
左值引用:
右值引用:
指針:
指針與引用的區別:
引用:
在C++中,?引用?是一種為已存在變量創建別名的機制,它允許通過不同的名稱訪問同一塊內存空間的數據。
上述圖對應的引用代碼:
int a=1;
int &b=a;
先初始化定義一個變量a,編譯器會為變量a開辟一個存儲空間并存儲值。然后又對變量a進行了一個引用將變量b綁到變量a的內存地址,不會額外占用內存空間,也就是變量b是變量a的別名,變量a和變量b的地址都是一樣的,對同一塊內存空間進行管理。變量b也能訪問變量a中的值并且也能進行修改。
訪問變量a的存儲空間中的值需要先知道變量a的地址。我們可以把變量a的存儲空間看成一個房間,而變量a的地址就是這個房間的門牌號,變量b對變量a進行一個引用,就相當于把變量b也當成變量a的房間號,然后通過變量b也能夠找到該房間。變量a和變量b都這間房間的門牌號,無論誰對房間里面的值進行修改,變量a和變量b的值都會發生變化。
注意:
引用前必須進行初始化:引用在創建時必須被初始化,它必須指向某個已存在的對象。
一旦綁定之后,不可改變:引用一旦被初始化后,它將一直保持與其初始對象的綁定,不能改變為另一個對象的引用。
沒有空引用:引用必須指向某個對象,不能存在空引用。
左值引用和右值引用:
左值引用:
表示持久化對象,具有明確內存地址(可&
取址),可以被多次賦值,可出現在賦值符號左側或右側。可以被多次賦值。
右值引用:
表示臨時對象或字面量,無持久地址(不可&
取址),僅能出現在賦值符號右側。主要用于是在函數參數和返回值中,以實現更高效的資源管理和更靈活的代碼編寫方式。
指針:
指針是存儲內存地址的變量,通過地址間接訪問數據。其值為另一個變量的內存位置直接地址,而不是數據本身。引用本身不是一個對象,不能定義只想引用的指針。
int a = 10;
int *b = &a;
初始化定義變量a,編譯器會為其開辟一個空間并存儲值。"int *b = &a"將變量a的地址進行賦值給變量b,因為變量b也是一個變量,所以編譯器也會其開辟一個存儲空間,將變量a的地址存儲到變量b的內存空間中。
指針的地址也可以用另一個指針進行存儲。
int a = 10;
int *b= &a;
int **c = &b;
使用一個指針c將指針b的地址存儲到其存儲空間中。如果想要通過其存儲的地址進行訪問到變量a具體的值,那么就可以進行解引用操作來進行訪問。
std::cout<<"a的值"<<a<<std::endl;
std::cout<<"通過指針b訪問"<<*b<<std::endl;
std::cout<<"通過指針c訪問"<<**c<<std::endl;
指針c通過一次解引用"*c"得到的就是指針b也就是變量a的地址,因為指針c中存儲的是變量b的地址,c就代表變量b的地址,那么對c進行一次解引用就會得到指針b中存儲的內容。再對指針b進行一個解引用"*b"那么就相當于對指針c進行了兩次解引用操作"**c"就是對指針b中存儲的內容(變量a的地址)進行一次解引用,那么就會得到變量a中的值。
指針的一個運算:
數組的數組名就是一個指向數組的首元素的指針,如果定義一個指針存儲數組首元素的地址進行一個自增的話,因為數組是一塊連續的內存空間,根據數組存儲的數據類型占用的字節大小,來進行一個首元素地址,也就是起始地址來進行偏移,得到下一個元素的內存地址。
注意:數組名是一個常量指針,不可以修改指向,對數組名進行修改是非法的。可以通過數組名+i,來進行一個數組中元素的偏移地址。
int arr[10] = {0};
int *p = arr;
std::cout<<p<<std::endl;
p++;
std::cout<<p<<std::endl;
可以用上述方式進行一個驗證。
指針與引用的區別:
指針可以不用進行初始化,引用必須進行初始化。
指針是一個變量,編譯器會為其分配存儲空間,而引用不是一個對象,不會為其分配存儲空間。
指針可以進行多級引用,而引用不可以多級引用。
指針在其生命周期內可以修改指向的對象,而引用一旦綁定對象之后,則不可以進行修改。
對指針進行計算大小:sizeof(指針)的大小與指向的數據類型無關,在32位系統中為4字節,在64為系統中占8字節,而引用不同,因為引用本身不占獨立的存儲空間,sizeof(引用)的大小是其綁定對象的大小。
指針可以為空,而引用不能為空,必須綁定對象。