標籤:
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是否安全?
C++強制類型轉換操作符 const_cast