C++指針、引用與取地址運(yùn)算符對(duì)比分析
一、引言
在學(xué)習(xí) C++ 的過(guò)程中,初學(xué)者很容易會(huì)被這幾個(gè)概念搞混:
- 指針(Pointer)
- 引用(Reference)
- 取地址運(yùn)算符(&)
尤其是初學(xué)者,經(jīng)常會(huì)問(wèn):
int* p和int *p有區(qū)別嗎?&到底是取地址還是引用?- 指針和引用是不是一回事?
這篇文章幫你一次性徹底搞懂這些核心概念。
二、一句話快速理解
- 指針:存儲(chǔ)“地址”的變量
- 引用:變量的“別名”
- &:取地址運(yùn)算符(同時(shí)也用于定義引用)
三、指針(Pointer)
1?? 基本定義
int a = 10; int* p = &a;
含義:
p存的是a的地址*p才是訪問(wèn)a的值
2?? 指針的特點(diǎn)
可以修改指向
int b = 20; p = &b;
可以為空
int* p = nullptr;
需要解引用訪問(wèn)
cout << *p;
四、引用(Reference)
1?? 基本定義
int a = 10; int& r = a;
含義:
r就是a的另一個(gè)名字
2?? 使用效果
r = 20; // 此時(shí) a 也變成 20
3?? 引用的特點(diǎn)
必須初始化
不能重新綁定
使用時(shí)像普通變量(不需要 *)
五、取地址運(yùn)算符&
int a = 10; int* p = &a;
&a 表示:獲取變量 a 的地址
?? 注意:& 有兩種用途!
int& r = a; // 定義引用 int* p = &a; // 取地址
下面用一個(gè)表格對(duì)上面的內(nèi)容做一個(gè)總結(jié):
| 特性 | 指針 | 引用 | &運(yùn)算符 |
|---|---|---|---|
| 本質(zhì) | 變量 | 別名 | 操作符 |
| 是否占內(nèi)存 | 是 | 是(通常實(shí)現(xiàn)為指針) | 否 |
| 是否可為空 | ? | ? | - |
| 是否可改變指向 | ? | ? | - |
| 使用方式 | *p | 直接用 | &a |
| 安全性 | 較低 | 更安全 | - |
在 C/C++ 中,取地址運(yùn)算符
&得到的是變量在程序中的“內(nèi)存地址”,但這個(gè)地址本質(zhì)上是由操作系統(tǒng)提供的虛擬地址,而不是真實(shí)的物理內(nèi)存地址;程序可以通過(guò)這個(gè)地址訪問(wèn)數(shù)據(jù),但底層還需要經(jīng)過(guò)操作系統(tǒng)和硬件(如內(nèi)存管理單元)的轉(zhuǎn)換才能映射到實(shí)際的物理內(nèi)存。
六、進(jìn)階與易錯(cuò)點(diǎn)總結(jié)
6.1int *p和int* p的區(qū)別
很多人會(huì)糾結(jié)這一點(diǎn),其實(shí)結(jié)論很簡(jiǎn)單:
兩者完全等價(jià),沒(méi)有任何本質(zhì)區(qū)別
int *p; int* p;
都表示:p 是一個(gè)指向 int 的指針,編譯器處理完全一致
6.1.1 為什么會(huì)有兩種寫(xiě)法?
因?yàn)樵?C++ 中:
* 實(shí)際是“修飾變量”,不是類(lèi)型的一部分
看下面代碼:
int* p1, p2;
實(shí)際含義是:
p1是指針p2是普通int
這也是很多初學(xué)者踩坑的地方
6.1.2 推薦寫(xiě)法
int *p1, *p2;
或者:
int* p1; int* p2;
保持風(fēng)格統(tǒng)一最重要
6.2 指針 vs 引用(核心對(duì)比)
| 特性 | 指針 | 引用 |
|---|---|---|
| 本質(zhì) | 存地址的變量 | 變量別名 |
| 是否可為空 | ? | ? |
| 是否可改指向 | ? | ? |
| 訪問(wèn)方式 | *p | 直接使用 |
| 安全性 | 較低 | 更安全 |
其中:
- 指針更靈活,但更容易出錯(cuò)
- 引用更安全,但限制更多
6.3 函數(shù)傳參對(duì)比(高頻考點(diǎn))
指針傳參
void func(int* p) {
*p = 100;
}
func(&a);引用傳參
void func(int& r) {
r = 100;
}
func(a);6.4 相關(guān)擴(kuò)展知識(shí)
6.4.1 解引用運(yùn)算符*
*p
通過(guò)地址來(lái)訪問(wèn)變量
6.4.2 常量指針
const int* p; // 不能修改指向的值,可以修改指針本身! int* const p; // 不能修改指針本身
6.4.3 右值引用(C++11 核心特性)
6.4.3.1 什么是右值引用?
int&& r = 10;
&& 表示 右值引用(rvalue reference)
6.4.3.2 左值引用 vs 右值引用
int a = 10; int b = a; // a 是左值 int c = 10; // 10 是右值
核心區(qū)別:
| 類(lèi)型 | 特點(diǎn) | |
|---|---|---|
| 左值(lvalue) | 有名字、可取地址 | |
| 右值(rvalue) | 臨時(shí)值、不能取地址 |
6.4.3.3 為什么需要右值引用?
為了解決一個(gè)核心問(wèn)題:避免不必要的拷貝,提高性能
看一個(gè)例子:
std::string s1 = "hello"; std::string s2 = s1; // 拷貝(慢)
如果是臨時(shí)對(duì)象(右值),它本身馬上就要被銷(xiāo)毀,如果還像普通變量一樣進(jìn)行拷貝,就會(huì)產(chǎn)生一次不必要的內(nèi)存復(fù)制(比如 std::string、vector 這種內(nèi)部帶堆內(nèi)存的數(shù)據(jù)結(jié)構(gòu)),既浪費(fèi)時(shí)間又浪費(fèi)空間;而引入右值引用(&&)后,程序可以直接“接管”這個(gè)臨時(shí)對(duì)象內(nèi)部已經(jīng)分配好的資源(如指針指向的內(nèi)存),而不是重新申請(qǐng)和復(fù)制,這就是“移動(dòng)語(yǔ)義”。右值引用的本質(zhì)作用就是:針對(duì)臨時(shí)對(duì)象,避免不必要的拷貝,通過(guò)資源轉(zhuǎn)移來(lái)提升性能,同時(shí)保持代碼安全(由對(duì)象自動(dòng)管理資源)
6.4.4 智能指針(現(xiàn)代 C++ 必備)
6.4.4.1 為什么需要智能指針?
傳統(tǒng)指針的問(wèn)題:
int* p = new int(10); // 忘記 delete → 內(nèi)存泄漏
常見(jiàn)問(wèn)題:
- 內(nèi)存泄漏
- 重復(fù)釋放
- 懸空指針
6.4.4.2 智能指針的本質(zhì)
用對(duì)象管理指針(RAII思想)
#include <memory>
把原本需要手動(dòng) new/delete 的指針資源,交給一個(gè)對(duì)象來(lái)負(fù)責(zé)生命周期,這個(gè)對(duì)象在構(gòu)造時(shí)獲取資源,在析構(gòu)時(shí)自動(dòng)釋放資源,從而避免內(nèi)存泄漏和忘記釋放的問(wèn)題。
6.4.4.3 三種常用智能指針
std::unique_ptr<int> p = std::make_unique<int>(10); // 獨(dú)占所有權(quán) std::shared_ptr<int> p1 = std::make_shared<int>(10); // 共享所有權(quán) std::shared_ptr<int> p2 = p1; std::weak_ptr<int> wp = p1; //解決循環(huán)引用
到此這篇關(guān)于C++指針、引用與取地址運(yùn)算符對(duì)比分析的文章就介紹到這了,更多相關(guān)C++指針、引用與地址運(yùn)算符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(15.三數(shù)之和)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(三數(shù)之和),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C語(yǔ)言中sscanf()函數(shù)的字符串格式化用法
這篇文章介紹的是C語(yǔ)言中sscanf()函數(shù),本文介紹了sscanf()函數(shù)的含義與用法,對(duì)大家日常使用C語(yǔ)言的sscanf()函數(shù)很有幫助,有需要的可以參考借鑒。2016-08-08
詳解c++11以正確的姿勢(shì)輸出enum class的值
這篇文章主要介紹了詳解c++11以正確的姿勢(shì)輸出enum class的值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
C/C++使用socket實(shí)現(xiàn)判斷ip是否能連通
這篇文章主要為大家詳細(xì)介紹了C/C++如何使用socket實(shí)現(xiàn)判斷ip是否能連通,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-07-07

