指向const常量的指針可以修改常量的值
實例
先直接看代碼:
int main(int argc, char const* argv[])c
{
const int a = 100;
const int* pa = &a;
int* pa_1 = &a;
//*pa = 3; // 編譯不過,指針常量不能通過指針修改值
int* b = const_cast<int*>(pa); // 把const轉換掉
*b = 3;
cout << "a: " << a << endl; // 100
cout << "*b: " << *pa << endl; // 3
}
輸出結果:
a:100
*pa:3
可以看到,指向a的指針的輸出值變為了100,但為什么a的值還是100呢,因為const int x = 100;這種情況,編譯器會認為x是一個編譯期可計算出結果的常量,那么x就會像宏定義一樣,用到x的地方會被編譯器替換成100。如果我們將其變為運行時初始化:
int func()
{
return 100;
};
int main(int argc, char const* argv[])
{
const int a = func();
const int* pa = &a;
int* b = const_cast<int*>(pa); // 把const轉換掉
*b = 3;
cout << "a: " << a << endl; // 3
cout << "*pa: " << *pa << endl; // 3
}
輸出結果:
a:3
*pa:3
在這種情況下,a的輸出值也變成了 3 。再嘗試一下,通過constexpr的情況:
constexpr int func()
{
return 100;
};
int main(int argc, char const* argv[])
{
constexpr int a = func();
const int* pa = &a;
int* b = const_cast<int*>(pa); // 把const轉換掉
*b = 3;
cout << "a: " << a << endl; // 100
cout << "*pa: " << *pa << endl; // 3
}
輸出結果:
a:100
*pa:3
可以看到,借由constexpr賦予的常量表達式獲得在程序編譯階段計算出結果的能力,a的值重新變成了在編譯時初始化。
解決方法
對於這種情況,我們可以通過把局部const變量變成全局const變量。代碼如下:
const int a = 100;
int main(int argc, char const* argv[])
{
const int* pa = &a;
int* b = const_cast<int*>(pa); // 把const轉換掉
*b = 3;
cout << "a: " << a << endl;
cout << "*pa: " << *pa << endl;
}
這段代碼將不會正確運行。其原因是,全局常量的存儲位置是數據段的全局/靜態區,這個內存區是只讀的,而局部常量存放於堆棧中,雖然不能直接修改,但可以通過指針間接修改。