網站首頁 編程語言 正文
Const 的作用及歷史
const (computer programming) - Wikipedia
一、歷史
按理來說,要想了解一件事物提出的原因,最好的辦法就是去尋找當時的歷史背景,以及圍繞這件事所發生的故事。
可是非常抱歉,我并沒沒有找到C
語言中const
提出的背景,但是一個可以參考的歷史是,常量這種數據形式早在匯編語言中就有所體現,匯編語言中的constant
是一個確定的數值,在匯編階段就可以確定直接編碼在于指令代碼中,不是保存在寄存器中的可以變化的量。
常量是需求,C
語言沒理由不保留這個傳統,自然而然的const
關鍵字出現了。
二、C和C++的異同點
顧名思義,const
最基礎的作用就是保證數據不會被修改,僅僅可讀而已。這就好比一份沒有write
權限的文件一樣,只能遠觀而已。
const
是C語言32個關鍵字(C++中有49個)中的一個,主要起類型修飾的作用,可以理解為變量的屬性,比方說const int a = 10
從右往左看int a = 10
是定義并初始化了一個變量a
等于10,隨后使用const 修飾這個變量,告訴編譯器,這個變量是不可修改的。為了維護程序的安全性,由于const
一旦修飾就無法再更改了,那么const int a;
會生成一個值隨機且永遠無法修改的量,這樣非常不安全,所以C
的編譯器會要求你必須在定義的時候就立馬初始化。從這里也可以看出const
關鍵字的強硬之處。
到底const該放在哪?
在詳細討論const的用法之前,必須首先明白,const
是C語言中的一個類型限定符(type quailier
),是類型的一個部分,且const
越靠近誰,就修飾誰是常量類型。
從C語言的基礎數據類型來看,基本上可以抽象為一下幾個類別
- 基礎數據類型(整型,浮點)
對于基礎數據類型,使用const就單純定義為一個不可修改的量,此時由于不涉及其他的類型限制符,所以
const
放在哪里都是有效的
const int i = 10
\(\Leftrightarrow\)int const i = 10
但是一般const
在前。
- 指針類型(指針)
相比于基礎數據類型,指針類型存在很大的不同。
不使用const
修飾的指針,此時表示該指針一定指向一個變量,當指向const修飾的變量是就會報錯
const int a = 10; int * ptr = a; // error
當const
放在 int *
前時,表示指針類型是 const int
類型,那么依據指針類型的定義,該指針必定指向一個const int
類型的量,即常量。
const int b = 100; const int * a = &b;
當const
放在 int *
后面時,int * const a
,顯然根據常規的指針類型的定義,我們只能推測出這是一個指向int
類型的指針,那么const
起什么作用呢?(見如下代碼)
int c = 10, b = 20; const int b = 30; int * const a = &c; // 此處沒有報錯,證明*號前面是指針類型,這條真理沒錯 //1. 可當我們嘗試修改指向的時候 a = &b; // 此處會報錯!這表明const靠近變量名的時候表示指針指向一個變量后就無法更改了 //2. 如果一開始就不初始化int * const a呢? int * const a; // 此處會報錯 //3. 如果嘗試讓他指向一個const量呢? int * const a = &b; // 此處會報錯
以此類推可以得到一個指向const變量的無法修改指向的指針
const int b = 10; const int * const a = &b;
所以可以給出總結
-
const
靠近變量名的時候表示指針必須指向一個類型與指針類型相同的變量 - 一旦指向就無法更改指向
- 無法指向常量
復雜數據類型(枚舉,結構,共用)
針對復雜類型,由于出現了簡單類型的嵌套,自然會有const
的嵌套關系,下面以結構體來舉例子
當const
嵌套在結構體內部時。
typedef struct a { const int b; int c; }A; int main() { A aa; aa.b = 10; // 此處會報錯 }
在C語言中,在結構體內部使用const修飾不會報錯的,但是此變量再也無法修改,意味著這是一個無效量,既無法初始化,也無法修改(但是得益于C++的面向對象機制,即使如此我們還是可以定義const
并且給他賦值)。
當定義結構體的時候使用const
const A bb;
此時也會報錯,而且相對來說比上面還嚴重,此時結構體內部的所有值都是亂的,且無法修改。
而C++中由于引入了幾種新的編程模式,const
的作用范圍又進一步被擴充。
類中屬性與成員函數
結構體的遺留問題(即類的常量屬性)
這里先來解決前面C語言中的結構體問題,需求是想在結構體內部定義const變量,知道結構體內部的變量是無法直接初始化的,而C++中結構體可以理解為類,只不過權限不同而已,同樣可以擁有構造函數。
那么是不是可以在構造函數中初始化呢?(下面代碼會報錯)
struct a { a() { b = 100; } const int b; };
不是我們想的那樣,不過也非常接近,對于初始化類的變量還有一種方法,使用初始化列表(類的初始化列表的優先級是非常高的)
struct a { a() : b(100) {;} const int b; };
或者還有
struct a { const int b = 100; };
利用C++特性直接賦值,而此段代碼在C語言中會報錯,這也是C與C++不同的一個地方。
如此就完美解決了結構體const
量 問題。
類的靜態變量vs const
變量
static
也是一個修飾符,確定的是變量的生存期。const
覺得變量的可讀性,有這樣一條語句在類中和main函數中存在不同的意義
static const int a; // 此語句在main中會報錯,由于未初始化 // 在類中不會
這是由于static不會影響const的表達,在main函數中說明此變量就是const類型,確實需要立馬賦值。而在類中可以不那么著急,可以把類中的static變量理解為一個申明,在類的外面或者里面直接定義都可以,不會報錯。
函數const
以及類成員函數的const
修飾
普通函數的const
函數const
首先想到的是const 變量返回值。但是這其實是沒太大意義的
const
修飾返回值其實完全沒有發揮作用,屬于無效修飾。同樣的使用const修飾形式參數的時候也是如此,并不會限定你傳入的是const
還是普通變量,本質在于這一過程發生原因是由于值傳遞,不論是返回const
還是使用const
修飾形式參數,內部都發生了變量的創建與賦值
那const
修飾形參的例子,
int fun(const int a) { // a = 10 會報錯 return a } int main() { int c = 10; int d = fun(c); // 不會報錯 }
如上,c傳入的時候是把c的值拿到,然后函數壓棧,創建一個const int
變量a
且立馬初始化為c
的值,如此就在函數內部生成了一個const
變量。跟傳入什么值完全沒有關系。
成員函數的const
尾修飾
這屬于C++的特性,成員函數尾巴加上一個const
限制此函數對對象的修改,且提高了代碼的可讀性。
class A { private: int a; public: static int B; int getA() const { A::B = 100; // 此處不會報錯 a = 100; // 這里會報錯 return a; } }; int A::B = 100;
使用const
修飾成員函數會使該函數變成const member function
此類型無法修改對象的數據,但是可以修改可修改的靜態變量。
- 引用
引用相對來說沒有指針那么多的變種,引用的const
修飾也僅僅局限于讓引用變量無法修改指向這一點上。
- 在補充一點
const修飾類靜態整型變量的時候可以在類內部直接初始化(浮點數仍然是不行的)。
原文鏈接:https://www.cnblogs.com/mushrain/p/15674765.html
相關推薦
- 2022-11-12 PostgreSQL邏輯復制解密原理解析_PostgreSQL
- 2022-04-26 MFC修改編輯框光標顯示位置方法詳解_C 語言
- 2022-11-11 C#中的Hashtable?類使用詳解_C#教程
- 2022-09-17 C++基于boost?asio實現sync?tcp?server通信流程詳解_C 語言
- 2024-07-13 spring實現定時任務的動態可配置、可刪除、可啟用停用功能
- 2022-04-20 python日志模塊loguru詳解_python
- 2022-05-18 C/C++實現segy文件的讀取詳解_C 語言
- 2022-05-18 Matlab實現多子圖同步調整視角_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支