頂層const和底層const

baobaobashi發表於2024-05-07

什麼是 頂層const底層const

頂層const:表示指標是一個常量。
底層const:表示指標所指向的物件是一個常量。

1、例子

指標中const

const int *const p = new int(10); 

第一個const是底層const ,第二個是頂層const。

普通變數中const

const int a = 10;
int const b = 10;

因為是普通變數所以不區分頂層或是底層const,不論const的位置在哪,都宣告瞭這個變數不允許被修改。

引用中的const

const int ci = 10;
const int& c = ci;

用於宣告引用的const都為底層const

2、原因

當執行物件的複製操作時,常量是頂層const還是底層const的區別明顯。其中頂層const可以忽略,但是底層const不能忽略

我們進行分析:

const int *const p = new int(10);
int *p1 = p;
int *const p2 = p;
const int *p3 = p;

如下所示,我們忽略所有的頂層const:

const int* p = new int(10);
int *p1 = p;    //error:型別不一致
int *p2 = p;    //error:型別不一致
const int *p3 = p;  //right:變數型別一致

其次我們繼續觀察:

const int* p = new int(10);
int *p1 = p;    //error

此處我們未修飾p的指向,但是使用了const修飾了p的值。
如果第二句可以執行,我們可以接著執行這一句 * p1 = 10。那麼
p的值也會發生改變,這和我們開始約定的 const int* p出現了衝突,所以出現錯誤。

還有一個容易出現的誤區:

const int a = 10;
int *p4 = &a;   //error

這裡 &a存放的是a的地址,const修飾a的值不可改變,但是沒有說明a的地址不可以改變。我們將它看作一個指標,也就是a的地址可以進行改變,a中存放的內容不可改變。也就間接的可以看作是一個底層const修飾的 &a。底層const不可忽略,所以出現問題。
改正如下:

const int a = 10;
const int *p4 = &a; //同樣是頂層const修飾

引用中的const



    int &r3 = r1;
    int &r4 = 40;

原則:

  • 引用不是物件且不會複製,所以和頂層const或者底層const的邏輯不通用
  • 常量引用如果在左側,那麼右側可以接任何東西。
int *p1 = &c;
const int *p2 = &c;
const int *const p3 = &c;

const int &r1 = 20;
const int &r2 = *p1;
const int &r3 = *p2;
const int &r4 = *p3;
  • 非常量引用 = 常量 ×
int &r5 = 10;   //error
  • 引號在等號右側時,忽略&
const int &r6 = 10;
int &r7 = r6;

//忽略等號右側的&
int &r7 = const int r6;     //error:型別不匹配
  • 非常量 = 常量引用 √
int b = r6;

相關文章