網站首頁 編程語言 正文
在C++中,const作用于指針時,可以看做是對指針權限的限制。這里我們先把指針的權限歸為兩種,分別為指向權限和修改權限。(ps:以上是為了理解方便,實際并沒有如此規定)
int a = 10, b = 20; int* p = &a; p = &b; // 改變指向的權限 ? *p = 30; // 修改內存的權限 ? const int* cp = &a; // 限制修改權限 //*cp = 100; // error:表達式必須是可修改的左值 修改 ? cp = &b; // ok. 指向 ? int* const pa = &a; // 限制指向權限 *pa = 100; // ok. 修改 ? //pa = &b; // error:表達式必須是可修改的左值 指向 ?
指針的賦值一般遵守權限縮小式的賦值。例如,我有一本書,我有使用權限(我可以看,可以做筆記),借給你后你只有閱讀權限(只能看,不能做筆記)。當然,如果我們關系好,我可以賦予你使用權(你擁有讀寫的權利)。同樣的,指針的賦值也是如此。
int a = 10; int* p = &a; // int* <== int * int* q = p; // int* <== int* const int* cp = p; // const int* <== int* 權限縮小,? int* const pa = p; // int* <== int* 注意:int* const pa;是“int*”類型 //int* p1 = cp; // error:int* <== const int * 權限放大,? int* p2 = pa; // ok. int* <== int*
我們可以得出一級指針賦值的公式
int * <== int * // int* 包含 int* 和 int* const類型 int const * <== int * // int const * <=等同=> const int * // 以上公式反過來賦值就是錯誤的..
練習一:一級指針指向練習題
題目一:下列表達式語句賦值錯誤的是?
int a = 10; const int* p = &a; int* q = p; int a = 10; int* const p = &a; int* q = p; int a = 10; int* const p = &a; int* const q = p; int a = 10; int* const p = &a; const int* q = p;
答案:(鼠標選中查看)
?錯誤:A,正確:B、C、D?
解析:
int a = 10; const int* p1 = &a; int* q1 = p1; // error:無法從const int * 轉為 int * /* 分析: int* <= cosnt int* */ int* const p2 = &a; int* q2 = p2; /* 分析: int* <= int* */ int* const p3 = &a; int* const q3 = p3; /* 分析: int* <= int* */ int* const p4 = &a; const int* q4 = p4; /* 分析: cosnt int* <= int* */
練習二:二級指針指向練習題
題目二:下列表達式語句錯誤的有。
// 選項A int a = 10; int* p1 = &a; const int** q1 = &p1; // 選項B int a = 10; int* p2 = &a; int* const* q2 = &p2; // 選項C int a = 10; int* p3 = &a; int** const q3 = &p3; // 選項D int a = 10; int* const p4 = &a; int** q4 = &p4; // 選項E int a = 10; const int* p5 = &a; int* const* q5 = &p5;
答案:(鼠標選中查看)
?錯誤:A、D、E,正確:B、C?
A選項;
錯誤; 注:如果const修飾的是二級指針,我們需要對二級指針的逐層解引用進行分析。
int* p1 = &a; const int** q1 = &p1; //error 無法從“int * *”轉換為“const int** ”
int* p1 = &a;
?p1的類型為int*
?取地址為?int **
const int** q1 = &p1;
?q1的類型為?const int **
則指針賦值過程為?const int ** <= int* *
分析:
- const作用于(**q1),修飾二級指針。表示不可通過q1對?
a
?的值進行修改。 - *q1?解引用一次后,為一級指針,即?p1?。但是?p1?存在對?
a
?修改的風險,因此無法直接賦值。
修改方案:
- 方案一:直接限定一級指針p1。保證p1不會修改a的值,即
const int * p1= &a;
?const int** q1 = &p1;
- 方案二:間接限定q1,使其指向時縮小權限,對解引用后的(*q1)修改的權限做出限制,如:
const int * const * q1;
// 方案一 const int* p12 = &a; const int** q12 = &p12; // 方案二 int* p11 = &a; const int* const* q11 = &p1;
B選項;
正確; 注:如果const修飾的是一級指針,我們可以拋開二級指針的表象,但看一級指針的賦值操作是否正確。如本例。
int* p2 = &a; int* const* q2 = &p2; /* 分析: int* const* <== int* * const修飾 *q2,即cosnt修飾一級指針 cosnt* <== * // 去掉前面的 int* <= int* int const * <== int * // 添加一個任意類型,如int 如?所示,這是一個權限縮小的一級指針賦值,? */
C選項;
正確; 注:如果兩邊類型相同,則無需進行判斷。如本例。
int* p3 = &a; int** const q3 = &p3; cout << typeid(q3).name() << endl; //輸出 q3 類型 int * * /* 分析: int**const <== int* * 即 int** <== int* * 兩邊類型相同,無需進行特殊判斷,? */
ps:如果const修飾的參數右邊無“*”號,則該cosnt不作用于類型。如:
int n = 10; // 使用typeid(valtypr).name() 輸出變量類型 int const* p1 = &n; // int const * int* const p2 = &n; // int * // 忽略const int* p = &n; int** q = &p; //int const** q1 = &p; int const* const* q1 = &p; // int const* const* int* const* q2 = &p; // int* const* int** const q3 = &p; // int** // 忽略cosnt
D選項;
錯誤; 同B選項相同,對于const修飾的一級指針進行判即可。
int* const p4 = &a; int** q4 = &p4; //error "int *const *"類型的值不能用于初始化"int **類型的實體
int* const p4 = &a;
?類型為?int*
,因為const的存在,取地址后類型為?int * const *
int** q4 = &p4;
?類型為?int**
則指針賦值過程為?int** <== int* const*
分析:
- const作用于(p4),修飾一級指針。則我們忽略沒有const修飾的部分。即
* <== const*
?,//忽略?int?部分,該部分賦值時權限沒有發生變化。int* <== int const *
?,給指針確定一個類型,如“int” 類型 - 如?,我們可以看到,該表達式語句想從int const* 類型處,獲得一個?int* 類型的賦值,也就是說這是權限放大式的賦值。錯誤原因:該賦值會使得 int* 類型指針對常量(int const* 所指向的值)產生修改的風險。
修改方案:
- 把
int* <== int const *
型賦值改成?int const* <== int const *
類型賦值即,int*const* q4 = &p4;
?
E選項;
錯誤; 注:如果賦值兩邊都有const時,各論各的分析,如下。
const int* p5 = &a; int* const* q5 = &p5; //error 無法從"const int **"轉換為"int *const *"
分析:
- 省略分析過程等賦值類型為?
int* const* <== const int* *
- 分情況分析:
- 提取指針左邊部分:
int* <== const int*
?,錯誤 ? - 提取指針右邊部分:
cosnt * <== *
?即?int const * <== int *
,正確 ?
- 提取指針左邊部分:
- 綜上,錯誤 ?。
修改方案:
1.修改指針左邊類型:int* <== const int*
???int* <= int*
2.修改指針左邊類型:int* <== const int*
???const int* <= const int*
//1 int* <= int* int* p51 = &a; // const int* p5 ? int* p51 int* const* q51 = &p51; //2 const int* <= const int* const int* p52 = &a; const int* const* q52 = &p52; // int* const* q5 ? const int* const* q52
方法總結:
對于二級指針的賦值操作判斷,看const位置、主要有以下兩種情況:
- 如果?const修飾的是二級指針?如:
-
int const **
?,如選項A。我們需要考慮其解引用情況。cosnt修飾二級指針所指向的值為常量,但是由于一次解引用后的指針會存在修改常量的風險,因此我們需要限制該指針與常量之間進行過度的一級指針 - 針對此類二級指針,我們只需記住合法的賦值為等式兩邊需同時有const?,
const int* cosnt* <== int**
或?左邊等式有兩個cosnt?,const int* cosnt* <== int**
?。
-
- 如果?const修飾的是一級指針或其他?如:
1.const修飾的是一級指針,int * const *
,如選項B。單獨剝離出含cosnt類型的一級指針類型進行分析
2.即修飾一級指針又修飾二級指針?如,?int cosnt * cosnt *
3.無const修飾?如,?int**
?或?int ** cosnt
,如選項C、選項D
- 針對此類二級指針,通過一級指針的比較進行比較即可。
總結
原文鏈接:https://blog.csdn.net/weixin_43919932/article/details/108632601
相關推薦
- 2022-05-10 筆記本能連接 WiFi,但在瀏覽器中并不能訪問網頁的問題的四種方案;
- 2022-04-20 C語言進階棧幀示例詳解教程_C 語言
- 2024-02-28 UNI-APP設置屏幕保持常亮
- 2022-06-12 Python語法學習之線程的創建與常用方法詳解_python
- 2021-12-02 C++?函數的介紹_C 語言
- 2023-11-18 Python list寫入txt文件
- 2023-03-02 SQLServer?清理日志的實現_MsSql
- 2023-07-07 什么是依賴注入?可以通過多少種方式完成依賴注入?
- 最近更新
-
- 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同步修改后的遠程分支