網站首頁 編程語言 正文
1 概述:const和define的區別
先看一個典型的程序:
#include<iostream> using namespace std; int main() { int num = 1; #define t1 num + num #define t2 t1 % t1 cout << "t2 is " << t2 << endl; // t2 is 2 const int s1 = num + num; const int s2 = s1 % s1; cout << "s2 is " << s2 << endl; // s2 is 0 return 0; }
運行結果如注釋所示,分別得到“t2 is 2”、“s2 is 0”???
分析原因:const定義的常量s1、s2,則s1的值是num+num,s2的值是s1%s1,所以最后結果為“s2 is 0”;而define定義的變量作替換后,C++把cout<<"t2 is "<<t2<<endl;語句譯成了:cout<<"t2 is "<<num+num%num+num<<endl;所以結果為“t2 is 2”(1+0+1=2)
注意:define定義的內容,建議增加使用括號()
#define t1 (num + num) #define t2 (t1 % t1)
具體分析define與const的區別,如下定義:
const float PI = 3.14; #define PI (3.14)
- 類型的安全性檢查:const常量有數據類型,而define定義宏常量沒有數據類型。則編譯器可以對前者進行類型安全檢查,而對后者只進行字符替換,沒有類型安全檢查(字符替換時可能會產生意料不到的錯誤,如上面的程序所示);
- 調試:部分調度工具可以對const常量進行調度,但不能對宏常量進行調度;
- 編譯器的處理方式不同:define宏是在預處理階段展開,const常量則是編譯運行階段使用;
- 存儲方式不同:define宏僅僅是展開,有幾個地方使用則展開幾次,不分配內存;const常量會在內存中分配地址(可以是堆中也可以是棧中);
- 效率:define定義的常量在內存中有若干個拷貝;const定義的常量在程序運行過程中只有一份拷貝,甚至不為普通const常量分配存儲空間,而是將它們保存在符號表中,相當于沒有了讀內存的操作,使得效率也很高。
2. 修飾局部變量
const約束對象的訪問性質:使得對象只能讀,不能寫:不允許修改對象的值.
const 是constant 的縮寫,“恒定不變”的意思。被const 修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。所以很多C++程序設計書籍建議:“Use const whenever you need”。
const int n=5; int const n=5;
這兩種寫法是一樣的,都是表示變量n的值不能被改變了,需要注意的是,用const修飾變量時,一定要給變臉初始化,否則之后就不能再進行賦值了。
// C const int num = 100; (int *)&num = 4; //可以間接修改
C的const表示修飾只讀變量,但是我們可以惡意強制操作const對象。
接下來看看const用于修飾常量靜態字符串,例如:
const char* str="fdsafdsa";
如果沒有const的修飾,我們可能會在后面有意無意的寫str[4]=’x’這樣的語句,這樣會導致對只讀內存區域的賦值,然后程序會立刻異常終止。有了const,這個錯誤就能在程序被編譯的時候就立即檢查出來,這就是const的好處。讓邏輯錯誤在編譯期被發現。
如下修改都是不允許的。
// c++ const int i = 0; //是一個右值,有內存實體 i = 11; //錯誤:向只讀變量‘i'賦值 const int a{1.1}; //錯誤:從“double”轉換到“int”需要收縮轉換,請初始化成相同類型的常量
3. 常量指針與指針常量
常量指針是指針指向的內容是常量,可以有一下兩種定義方式。
const int * n; int const * n;
需要注意的是一下兩點:
1、常量指針說的是不能通過這個指針改變變量的值,但是還是可以通過其他的引用來改變變量的值的。
int a=5; const int* n=&a; a=6;
指針常量是指指針本身是個常量,不能在指向其他的地址,寫法如下:
int *const n;
需要注意的是,指針常量指向的地址不能改變,但是地址中保存的數值是可以改變的,可以通過其他指向改地址的指針來修改。
int a=5; int *p=&a; int* const n=&a; *p=8;
注意:區分常量指針和指針常量的關鍵就在于星號的位置,我們以星號為分界線,如果const在星號的左邊,則為常量指針,如果const在星號的右邊則為指針常量。如果我們將星號讀作‘指針’,將const讀作‘常量’的話,內容正好符合。int const * n;是常量指針,int *const n;是指針常量。
指向常量的常指針
是以上兩種的結合,指針指向的位置不能改變并且也不能通過這個指針改變變量的值,但是依然可以通過其他的普通指針改變變量的值。
const int* const p;
4. 修飾函數的參數
根據常量指針與指針常量,const修飾函數的參數也是分為三種情況。
1、防止修改指針指向的內容
void StringCopy(char *strDestination, const char *strSource);
其中 strSource 是輸入參數,strDestination 是輸出參數。給 strSource 加上 const 修飾后,如果函數體內的語句試圖改動 strSource 的內容,編譯器將指出錯誤。
2、防止修改指針指向的地址
void swap ( int * const p1 , int * const p2 )
指針p1和指針p2指向的地址都不能修改。
3、以上兩種的結合。
5. 修飾函數的返回值
如果給以“指針傳遞”方式的函數返回值加 const 修飾,那么函數返回值(即指針)的內容不能被修改,該返回值只能被賦給加const 修飾的同類型指針。
例如函數:
const char * GetString(void);
如下語句將出現編譯錯誤:
char *str = GetString();
正確的用法是
const char *str = GetString();
6. 修飾全局變量
全局變量的作用域是整個文件,我們應該盡量避免使用全局變量,因為一旦有一個函數改變了全局變量的值,它也會影響到其他引用這個變量的函數,導致除了bug后很難發現,如果一定要用全局變量,我們應該盡量的使用const修飾符進行修飾,這樣防止不必要的人為修改,使用的方法與局部變量是相同的。
總結
原文鏈接:https://blog.csdn.net/zou_albert/article/details/123846874
相關推薦
- 2022-05-17 ubuntu E: 無法獲得鎖 /var/lib/dpkg/lock-frontend - open
- 2022-10-01 React?hooks?useState異步問題及解決_React
- 2022-09-01 Linux實現項目的自動化部署_Linux
- 2022-04-30 詳解Matlab如何繪制小提琴圖_C 語言
- 2022-05-28 Entity?Framework?Core種子數據Data-Seeding_實用技巧
- 2022-10-20 Flutter?StatefulBuilder實現局部刷新實例詳解_Android
- 2022-08-21 Caffe卷積神經網絡solver及其配置詳解_python
- 2023-01-09 Android自定義ViewGroup實現九宮格布局_Android
- 最近更新
-
- 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同步修改后的遠程分支