深入了解C++中const的用法

文章目錄

    • 一、C++中的const如何理解?
    • 二、C++中的const與C語言中的const有何區別?
    • 三、const與指針、引用的結合使用

一、C++中的const如何理解?

在C++中,const是一個關鍵字,用來表示常量性,意在告訴編譯器某些變量或對象的值是不可修改的,從而提高代碼的安全性和可讀性。

二、C++中的const與C語言中的const有何區別?

1. 語義層面的不同

在C語言中,const更多地是一個承諾,它表示變量在當前作用域中不能被修改,但這種約束不是絕對的,可以通過特定的方式繞過,例如強制類型轉換。
在C++中,const語義更加嚴格和完善。它不僅約束變量,還能作用于成員函數、引用、指針等,且配合C++的類型系統,實現了更強的編譯時檢查。

2. const與引用

在C語言中沒有引用的概念,因此const無法結合引用使用。
C++支持常量引用,用來避免拷貝,提高效率,同時保護原始數據不被修改。

void func(const int& ref) {// ref 是只讀的,不能修改原始值
}

這種用法在C++中非常常見,特別是在傳遞大型對象時。

3. 修飾函數

C語言沒有成員函數的概念,因此const無法作用于函數級別。
C++允許const修飾成員函數,表示該函數不會修改對象的狀態。這種語義在面向對象編程中非常重要。

class MyClass {
public:void display() const { /* 不會修改成員變量 */ }
};

4.繞過const的方式
C語言可以通過強制類型轉換((int*))來繞過const的限制。在C語言中const修飾的變量,可以不用初始化,它不叫常量,而是叫常變量。

const int a = 20;
int *p = (int*)&a;
*p = 30;
printf("%d %d %d\n", a, *p, *(&a));

輸出結果:30 30 30

雖然C++也支持強制類型轉換,但C++提供了更安全的const_cast,明確表示是移除const限定符。

const int a = 10;
int* p = const_cast<int*>(&a);
*p = 20; // 合法,但可能導致未定義行為

5.編譯方式不同

在C語言中const就是被當作一個變量來編譯生成指令的。
在C++中,所有出現const常量名字的地方,在編譯時都被常量的初始化值替換了。且不能作為左值。

在C++中const用字面常量去初始化,如:

int main() {const int a = 20;//a是使用立即數進行的初始化,所以a為常量int array[a] = {};int* p = (int*)&a;*p = 30;std::cout << a << "," << *p << std::endl;return 0;
}

輸出結果:20,30

在C++中const用變量去初始化,如:

int main() {int b = 20;const int a = b;//a的初始值不是立即數,是一個變量,所以a此時為常變量//int array[a] = {}; //無法使用變量初始化數組int* p = (int*)&a;*p = 30;std::cout << a << "," << *p << std::endl;return 0;
}

輸出結果:30,30

三、const與指針、引用的結合使用

const修飾的變量常出現的錯誤是:

常量不能作為左值(不能直接修改常量的值)。
不能把常量的地址泄露給一個普通指針或者普通的引用變量(不能間接修改常量的值)。

int main() {const int a = 10;int b = 20;a = b; //錯誤:常量a不能再作為左值,表達式必須是可修改的左值int* p = &a; //錯誤: 不能將const int* 轉換為int*,這樣就會間接修改a的值return 0;
}

1.const和一級指針的結合
注意:const修飾的是離它最近的類型

const int *p:const離int最近,所以修飾的是int類型,而const修飾的表達式是*p,這個時候就不能再修改*p的值,即指針的指向不能再做修改(指針的指向是常量),但是指針的本身是可以被修改的,比如p = &b。換句話說就是p可以指向不同的int類型的內存,但是不能通過指針間接修改指向的內存的值。
int const *p:const離int最近,修飾的是int類型,所以const修飾的表達式是*p,作用同上。
int *const p:const離int*最近,修飾的是int*類型,所以const修飾的是p本身。即這個指針的本身是常量,所以一旦p初始化指向某塊內存,那么就不能再更改它的指向。但是可以通過指針解引用修改指向的內存的值。
const int *const p:其作用是const int *p與int *const p的結合。

int main() {int* q1 = nullptr;int* const q2 = nullptr;std::cout << typeid(q1).name() << std::endl;std::cout << typeid(q2).name() << std::endl;// const如果右邊沒有指針*的話,const是不參與類型的// 比如說下面的const p3,表明p3是一個常量,即指針的指向不能再做改變int a = 10;int* p1 = &a;const int* p2 = &a; // const int* 轉換為 int*int* const p3 = &a; // int* 轉換為 int*int* p4 = p3; //int* 轉換為 int*return 0;
}

2.const和二級指針的結合

const和二級指針結合的幾種方式

const int**q:const修飾的類型是int,而它修飾的表達式是**q,所以**q不能被賦值,但是*q可以被賦值,q本身可以被賦值。
int *const *q:const修飾的類型是int *,而它修飾的表達式是const *q,所以*q不能被賦值,但是**q可以被賦值,q本身也可以被賦值。
int ** const q:const修飾的類型是int**,而它修飾的表達式是q,所以q本身不能被賦值,但是*q和**q可以被賦值。

3.總結const和指針的類型轉換公式

int* 轉換為 const int* 是不可行的。
const int* 轉換為 int* 是可行的。
int ** 轉換為 const int** 是不可行的。
const int** 轉換為 int **是不可行的。
int** 轉換為int* const*是錯誤的。
int* const*轉換為int**是可行的

4.const和一級指針,引用的結合使用

//寫一句代碼:在內存的0x0018ff44處寫一個4字節的10
int *p = (int*)0x0018ff44;
int *const &p1 = (int*)0x0018ff44; //(非常量引用的初始值必須為左值)0x0018ff44已經為常量了,如果使用引用,需要使用const修飾
int *&&p2 = (int*)0x0018ff44; //也可以使用右值引用(什么是右值:沒內存,沒名字,即字面常量)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62838.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62838.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62838.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

EasyExcel設置表頭上面的那種大標題(前端傳遞來的大標題)

1、首先得先引用easyExcel的版本依賴&#xff0c;我那 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version> </dependency> 2、然后得弄直接的實體類&#xff0c;&…

純血鴻蒙崛起,原生Android挑戰?兩大操作系統巔峰對決,智能設備未來誰主沉浮?

鴻蒙HarmonyOS和原生Android系統雖然在一些方面相似&#xff0c;但在架構、設計理念、API、開發工具等方面存在一些差異。鴻蒙系統的目標是跨設備、分布式的操作系統&#xff0c;強調多設備協同和資源共享&#xff0c;而Android則主要集中在智能手機和移動設備領域。 下面將從…

計算機網絡:傳輸層、應用層、網絡安全、視頻/音頻/無線網絡、下一代因特網

目錄 &#xff08;五&#xff09;傳輸層 1&#xff0e;傳輸層尋址與端口 2&#xff0e;無連接服務與面向連接服務 3. 傳輸連接的建立與釋放 4. UDP 的優點 5. UDP 和 TCP 報文段報頭格式 6. TCP 的流量控制 7&#xff0e;TCP 的擁塞控制 8. TCP 傳送連接的管理 &#…

【前端開發】HTML+CSS網頁,可以拿來當作業(免費開源)

HTML代碼 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content_lizhongyu"widthdevice-width, initial-scale1.0"><title>小兔鮮兒-新鮮、惠民、快捷<…

CV(4)--邊緣提取和相機模型

前言 僅記錄學習過程&#xff0c;有問題歡迎討論 邊緣提取&#xff08;涉及語義分割&#xff09;&#xff1a; 圖象的邊緣是指圖象局部區域亮度變化顯著的部分,也有正負之分&#xff0c;暗到亮為正 求邊緣的幅度&#xff1a;sobel&#xff0c;Canny算子 圖像分高頻分量和低…

【信息系統項目管理師】高分論文:論信息系統項目的整合管理(陽光信訪工作平臺)

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 正文一、明確目標,制定項目章程二、精心規劃,制定項目管理計劃三、細心嚴謹,指導和管理項目執行四、組織學習,管理項目知識五、多措并舉,對項目進行有效的監控六、規范流程,控制項目整體變更七、嚴謹高效…

智能技術引領未來:自動圖像標注的創新應用與發展

&#x1f351;個人主頁&#xff1a;Jupiter. &#x1f680; 所屬專欄&#xff1a;傳知代碼 歡迎大家點贊收藏評論&#x1f60a; 目錄 概述算法原理核心邏輯效果演示使用方式參考文獻 參考文獻&#xff1a;需要本文的詳細復現過程的項目源碼、數據和預訓練好的模型可從該地址處獲…

C語言-排序

常見的排序算法分為以下四種&#xff0c;插入排序&#xff0c;選擇排序&#xff0c;交換排序&#xff0c;歸并排序。 一、插入排序 (一)直接插入排序 直接插入排序&#xff0c;將一段數組看做被分成已排序序列和未排序序列&#xff0c;排序過程是從未排序序列的元素開始&…

【Java筆記】LinkedList 底層結構

一、LinkedList 的全面說明 LinkedList底層實現了雙向鏈表和雙端隊列特點可以添加任意元素(元素可以重復)&#xff0c;包括null線程不安全&#xff0c;沒有實現同步 二、LinkedList 的底層操作機制 三、LinkedList的增刪改查案例 public class LinkedListCRUD { public stati…

網管平臺(基礎篇):路由器的介紹與管理

路由器簡介 路由器&#xff08;Router&#xff09;是一種計算機網絡設備&#xff0c;它的主要作用是將數據通過打包&#xff0c;并按照一定的路徑選擇算法&#xff0c;將網絡傳送至目的地。路由器能夠連接兩個或更多個網絡&#xff0c;并根據信道的情況自動選擇和設定路由&…

排序算法(2):選擇排序

問題 排序 [30, 24, 5, 58, 18, 36, 12, 42, 39] 選擇排序 選擇排序每次從待排序序列中選出最小&#xff08;或最大&#xff09;的元素&#xff0c;將其放到序列的起始位置&#xff0c;然后&#xff0c;再從剩余未排序元素中繼續尋找最小&#xff08;或最大&#xff09;元素…

Tongweb8命令行使用收集(by lqw)

文章目錄 聲明對應版本修改thanos用戶密碼部署應用到默認實例節點相關操作新增節點(一般一個服務器ip只能裝一個節點)啟動節點(需確認節點沒有運行)停止節點刪除節點節點新增應用節點查看應用節點啟動應用節點停止應用節點卸載應用(謹慎操作,卸載后應用就沒有了,建議備份后…

Artec Leo3D掃描儀在重型機械設備定制中的應用【滬敖3D】

挑戰&#xff1a;一家加拿大制造商需要有效的方法&#xff0c;為富于變化且難度較高的逆向工程&#xff0c;快速、安全、準確地完成重型機械幾何采集。 解決方案&#xff1a;Artec Leo, Artec Studio, Geomagic for SOLIDWORKS 效果&#xff1a;Artec Leo三維掃描代替過去的手動…

Nginx 限制只能白名單 uri 請求的配置

實際生產項目中&#xff0c;大多數時候我們會將后端的 http 接口通過前置 nginx 進行反向代理&#xff0c;對互聯網用戶提供服務。往往我們后端服務所能提供的接口服務是大于互聯網用戶側的實際請求的接口地址數量的&#xff08;例如后端服務一共有100個api接口&#xff0c;經過…

題海拾貝:力扣 141.環形鏈表

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《題海拾貝》 歡迎點贊&#xff0c;關注&#xff01; 1、題…

Vite快速構建Vue教程

步驟 1: 初始化項目目錄 創建一個名為 projects 的文件夾&#xff0c;作為存放所有 Vite 項目的根目錄。這個文件夾將容納多個獨立的 Vite 項目。 步驟 2: 創建 Vite 項目 右鍵點擊 projects 文件夾并選擇“在此處打開終端”或使用您偏好的代碼編輯器&#xff08;如 VSCode&…

深入理解 CSS 文本換行: overflow-wrap 和 word-break

前言 正常情況下&#xff0c;在固定寬度的盒子中的中文會自動換行。但是&#xff0c;當遇到非常長的英文單詞或者很長的 URL 時&#xff0c;文本可能就不會自動換行&#xff0c;而會溢出所在容器。幸運的是&#xff0c;CSS 為我們提供了一些和文本換行相關的屬性&#xff1b;今…

【NumPy進階】:內存視圖、性能優化與高級線性代數

目錄 1. 深入理解 NumPy 的內存視圖與拷貝1.1 內存視圖&#xff08;View&#xff09;1.1.1 創建視圖1.1.2 視圖的特點 1.2 數組拷貝&#xff08;Copy&#xff09;1.2.1 創建拷貝1.2.2 拷貝的特點 1.3 視圖與拷貝的選擇 2. NumPy 的優化與性能提升技巧2.1 向量化操作示例&#x…

HarmonyOS 5.0應用開發——屬性動畫

【高心星出品】 文章目錄 屬性動畫animateTo屬性動畫animation屬性動畫 屬性動畫 屬性接口&#xff08;以下簡稱屬性&#xff09;包含尺寸屬性、布局屬性、位置屬性等多種類型&#xff0c;用于控制組件的行為。針對當前界面上的組件&#xff0c;其部分屬性&#xff08;如位置屬…

機器學習支持向量機(SVM)算法

一、引言 在當今數據驅動的時代&#xff0c;機器學習算法在各個領域發揮著至關重要的作用。支持向量機&#xff08;Support Vector Machine&#xff0c;SVM&#xff09;作為一種強大的監督學習算法&#xff0c;以其在分類和回歸任務中的卓越性能而備受矚目。SVM 具有良好的泛化…