C++ 提供四種具名型別轉換運算子,各有嚴格適用範圍。本文系統整理四大轉換特性,並深入實測 const_cast 移除常量性的真實行為與風險。
| 運算子 | 用途 | 安全性 | 典型場景 |
|---|---|---|---|
static_cast |
編譯期已知的相關型別轉換 | 較安全(編譯期檢查) | 數值型別轉換、基類↔派生類指標(無虛繼承)、void* 轉具體指標 |
dynamic_cast |
執行期多型安全向下轉型 | 最安全(RTTI 檢查) | 多型基類指標/參考轉派生類,**需虛函式、啟用 RTTI** |
const_cast |
移除/添加 const/volatile |
**危險**(破壞常量承諾) | 呼叫非 const 正確的舊 API、實作邏輯常量但介面需非 const |
reinterpret_cast |
位元模式重新解釋(低層轉換) | 最危險(無語意檢查) | 指標↔整數、函式指標轉換、型別雙關 |
static_cast<TargetType>(expression)
dynamic_cast<TargetType>(expression)
const_cast<TargetType>(expression)
reinterpret_cast<TargetType>(expression)
#include <iostream>
using namespace std;
void Fun(int &value) { cout << "Fun(val) = " << value << endl; }
int main() {
const int val = 100;
int *ptr = const_cast<int*>(&val);
*ptr = 200; // 修改記憶體內容
cout << "&val: " << &val << endl;
cout << "ptr: " << ptr << endl;
cout << "val = " << val << endl; // 輸出 100!
cout << "*ptr = " << *ptr << endl; // 輸出 200
int &ref = const_cast<int&>(val);
ref = 300;
cout << "val = " << val << endl; // 仍為 100
cout << "ref = " << ref << endl; // 輸出 300
Fun(const_cast<int&>(val)); // 輸出 300
return 0;
}


mov eax, 64h ; 100 (0x64) 直接嵌入指令碼 mov [val], eax ; val 記憶體位置寫入 100 ; 後續所有使用 val 的地方直接用 64h 立即數
編譯器將 const int val = 100 視為**編譯期常數**,對所有讀取 val 的指令進行**常量傳播**,直接嵌入立即數 0x64。
*ptr、ref 讀取到新值(200、300)。val 讀取仍為 100:編譯器優化替換為立即數,繞過記憶體讀取。const 物件為 UB,編譯器**有權**假設常量不變並優化。const 全域/靜態變數置於 .rodata 段(硬體唯讀頁面),寫入觸發 SIGSEGV。const 正確的舊式 C API,但**確知該 API 不會修改資料**。
void legacy_api(char *buf); // 未加 const
const std::string data = "safe";
legacy_api(const_cast<char*>(data.data())); // 僅讀取,安全
const 成員函式(如 mutable 快取更新)。
mutable:允許 const 成員函式修改特定資料成員(快取、鎖、統計計數)。const 正確的多載版本。std::as_const (C++17):獲取 const 參考,避免誤用 const_cast。GCC/Clang:-Wcast-qual 偵測移除 const 的轉換。MSVC:/W4 部分偵測。