const_cast也是一個強制類型轉換操作符。《C++ Primer》中是這樣描述它的:
1.將轉換掉表達式的const性質。
2.只有使用const_cast才能將const性質性質轉化掉。試圖使用其他三種形式的強制轉換都會導致編譯時的錯誤。(添加const還可以用其他轉換符,如static_const)
3.除了添加const或刪除const特性,使用const_cast符來執行其他任何類型的轉換都會引起編譯錯誤。(volatile限定符也包括,不過我不怎么了解,本文主要說const)
對於第一點,轉換掉表達式的const性質,意思是可以改變const對象的值了嗎?一開始我的確是這樣子認為的,於是我敲出了如下的代碼:
int main() { const int constant = 26; const int* const_p = &constant; int* modifier = const_cast<int*>(const_p); *modifier = 3; cout<< "constant: "<<constant<<endl; cout<<"*modifier: "<<*modifier<<endl; system("pause"); }
然而程序並沒有像預想的那樣輸出兩個3,運行結果是這樣的:
看來C++還是很厚道的,對聲明為const的變量來說,常量就是常量,任你各種轉化,常量的值就是不會變。這是C++的一個承諾。
那既然const變量的值是肯定不會發生變化的,還需要這個const_cast類型轉化有何用?這就引出了const_cast的最常用用法:
如果有一個函數,它的形參是non-const類型變量,而且函數不會對實參的值進行改動,這時我們可以使用類型為const的變量來調用函數,此時const_cast就派上用場了。
例如:
void InputInt(int * num) { cout<<*num<<endl; } int main() { const int constant = 21; //InputInt(constant); //error C2664: “InputInt”: 不能將參數 1 從“const int”轉換為“int *”
InputInt(const_cast<int*>(&constant)); system("pause"); }
除此之外,還有另外一種情況const指針能夠派上用場。如果我們定義了一個非const的變量,卻使用了一個指向const值的指針來指向它(這不是沒事找事嘛),在程序的某處我們想改變這個變量的值了,但手頭只持有指針,這是const_cast就可以用到了:
int main() { int constant = 26; const int* const_p = &constant; int* modifier = const_cast<int*>(const_p); *modifier = 3; cout<< "constant: "<<constant<<endl; cout<<"*modifier: "<<*modifier<<endl; system("pause"); }
總結一下上文:const_cast絕對不是為了改變const變量的值而設計的!
在函數參數的傳遞上const_cast的作用才顯現出來。
>>>>>>>>>>>>>>>>>> >>>分割線>>>>>>>>>>>>>>>>>>>>>>>>>
const_cast中的未定義行為
上面的第一段程序,輸出變量constant與*modefier的地址后....
int main() { const int constant = 26; const int* const_p = &constant; int* modifier = const_cast<int*>(const_p); *modifier = 3; cout<< "constant: "<<constant<<" adderss: "<< &constant <<endl; cout<<"*modifier: "<<*modifier<<" adderss: " << modifier<<endl; system("pause"); }
運行結果:
它們的地址是一樣的,值卻不同。具體原因我還是不大清除。在另外一些博客中看到, *modifier = 3; 這種操作屬於一種“未定義行為”,也即是說操作結果C++並沒有明確地定義,結果是怎樣的完全由編譯器的心情決定。對於未定義的行為,我們只能避免之。
關於const_cast是否安全的討論
逛了一些網站,大致有如下觀點:
const_cast is safe only if you're casting a variable that was originally non-const. For example, if you have a function that takes a parameter of a const char *, and you pass in a modifiable char *, it's safe to const_cast that parameter back to a char * and modify it. However, if the original variable was in fact const, then using const_cast will result in undefined behavior.
也即是上文中所說的const_cast的二種適用情況。
I would rather use static cast for the adding constness: static_cast<const sample*>(this). When I'm reading const_cast it means that the code is doing something potentially dangerous, so i try to avoid it's use when possible.
也有人認為const_cast本身就給潛在危險帶來可能,所以還是盡可能不用它了。
當需要給變量添加const屬性時,使用更為安全的static_cast來代替const_cast。
這里附上討論鏈接。const_cast是否安全?