面試題:C++指針和引用有什么區
C++指針和引用有什么區別?
在 C++ 中,指針和引用都是用來訪問其他變量的值的方式,但它們之間存在一些重要的區別。了解這些區別有助于更好地理解和使用這兩種工具。
01
指針
指針(Pointer)
定義:
指針是一個變量,它存儲了一個內存地址。
指針的類型是指向的數據的類型。
聲明:
指針通常用星號 * 來聲明,例如 int *p; 表示 p 是一個指向 int 類型的指針。
賦值:
指針可以通過賦值操作來指向不同的地址,例如 p = &a;,其中 &a 是變量 a 的地址。
指針可以指向 nullptr 或 NULL(在 C++11 之后推薦使用 nullptr)表示不指向任何對象。
解引用:
使用星號 * 來解引用指針并訪問它所指向的數據,例如 *p = 10;。
內存管理:
指針需要手動分配和釋放內存(使用 new 和 delete)。
指針可以指向任何類型的內存,包括未初始化的內存區域。
安全性:
使用指針時需要特別小心,因為訪問無效或已釋放的內存可能導致程序崩潰或未定義行為。
代碼示例:
#include <iostream>
int main() {
int a = 10;
int *p = &a; // p 指向 a
*p = 20; // 修改 a 的值
std::cout << "a: " << a << std::endl; // 輸出 20
p = nullptr; // p 不再指向任何東西
*p = 30; // 錯誤!p 為 nullptr
return 0;
}
02
引用
引用(Reference)
定義:
引用是一個別名,它是一個已經存在的變量的另一個名字。
引用不是真正的變量,它不占用額外的存儲空間。
聲明:
引用通常用 & 符號聲明,例如 int &r = a; 表示 r 是變量 a 的引用。
賦值:
引用一旦初始化后就不能更改,也就是說,不能重新綁定到另一個對象。一旦綁定后,引用始終指向同一個對象。
初始化時必須立即綁定到一個對象,不能是 nullptr。
解引用:
引用本身就是一個左值(可以出現在賦值的左邊),因此不需要解引用即可訪問其綁定的對象,例如 r = 10;。
內存管理:
引用本身不涉及內存分配,它只是現有對象的一個別名。
引用通常用于傳遞大對象或作為函數返回值,以避免不必要的拷貝。
安全性:
使用引用相對安全,因為引用總是有效,不會指向不存在的對象。
代碼示例:
#include <iostream>
int main() {
int a = 10;
int &r = a; // r 是 a 的引用
r = 20; // 修改 a 的值
std::cout << "a: " << a << std::endl; // 輸出 20
// 下面的語句是非法的,因為引用不能重新綁定到另一個對象
// int b = 30;
// r = b; // 錯誤!r 不能重新綁定
return 0;
}
03
引用不占用內存空間
看下面示例代碼:
#include?<iostream>
int main() {
int a = 9;
int& b = a; // b 是 a 的引用
int* p = &a;
std::cout << "a 的地址: " << &a << std::endl;
std::cout << "b 的地址: " << &b << std::endl;
std::cout << "p 的地址:" << &p << std::endl;
return 0;
}
運行輸出:
可以看到引用b的地址和變量a的地址是一樣的,b就是a的一個別名,它不涉及到額外的內存分配。但是指針p是一個變量,指針本身也會占用內存。
在 C++ 中,引用的內存分配如下:
變量 a:
分配一塊內存空間存儲 a 的值。
引用 b:
不需要分配新的內存空間,它直接綁定到 a 上。
因此,無論在代碼中創建多少個引用,它們都不會占用額外的內存空間,只會占用現有變量的內存。
04
總結
指針:
指針是一個變量,存儲地址。
指針本身占用存儲空間。
指針可以初始化為空,可以重新指向其他地址。
引用:
引用不是一個變量,而是現有變量的別名。
引用本身不占用存儲空間。
引用不能初始化為空,一旦初始化后不能重新綁定到另一個對象