1. 程式人生 > >C++ 學習筆記(3) const_cast

C++ 學習筆記(3) const_cast

const_cast

C++的四種類型轉換關鍵字之一, const_cast , static_cast , dynamic_cast, reinterpret_cast 。

不可以去除一個 const 變數的 const 屬性。可以跨過 const 訪問原始變數( 和 const 變數不同 )。

很容易理解錯的一個例子:

#include <bits/stdc++.h>
using namespace std ;

int main () {
	const int data = 100 ;
	int *p = const_cast<int*>( &data ) ;

	cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
	cout << "  p  = " << *p << "\t地址 : " << p << endl << endl ;

	*p = 200 ;

	cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
	cout << "  p  = " << *p << "\t地址 : " << p << endl << endl ;

	cout << "實際記憶體中的內容 : " << *(int*)(0x6ffe34) << endl << endl ;

	return 0 ;
}
實際執行結果, 編譯器 g++ , 支援 C++14


很奇怪? data 的地址是 0x6ffe34, p 指向的地址也是 0x6ffe34, 但是修改 p 之後, 同一個地址上的內容卻不相同。

可能是 const 的問題? const 的機制,就是在編譯期間,用一個常量代替了 data。

關鍵在這裡:

#include <bits/stdc++.h>
using namespace std ;

int main () {
	const int volatile data = 100 ;
	int *p = const_cast<int*>( &data ) ;

	cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
	cout << "  p  = " << *p << "\t地址 : " << p << endl << endl ;

	*p = 200 ;

	cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
	cout << "  p  = " << *p << "\t地址 : " << p << endl << endl ;

	cout << "實際記憶體中的內容 : " << *(int*)(0x6ffe34) << endl << endl ;

	return 0 ;
}
執行結果正常, data 地址和 p 指向的地址一致,內容也是一致的,都是修改後的 200 。



可以注意到,程式的差別就在一個 volatile , volatile 的作用是取消編譯器的優化,每一次使用該記憶體資訊,都很小心地重新讀取這塊記憶體的內容。如果沒有 volatile, 編譯器會採取一些優化,例如把 const 變數拷貝一份放在暫存器中( 或者類似於 cache,這樣速率就高 ), 沒有 volatile 就意味著,程式一直呼叫的 const  data 都是一份拷貝,不僅含有該 const 變數的地址,,還含有該 const 變數的資訊,不允許修改,但,不是真正的那個記憶體。真正的記憶體資訊通過 const_cast 改變了,但是一般無法獲取到該記憶體的資訊( 因為首先是考慮暫存器中的那份拷貝 )。

volatile 就可以重新,穩定地讀取該 const 常量真正記憶體的資訊,如果被改變了,也可以得到記憶體資訊。

第一個程式的 data 不是 const 常量的真正記憶體,只是一份在暫存器的拷貝, 不允許改變的拷貝。但是,缺點就是如果 const 變數經過一些方式被改變了,暫存器中的拷貝就會有 “延遲” 。

第二個程式, 在 volatile 的作用下,每次要使用 data 時都需要重新讀取原地址,一直都是原始的那份記憶體,優點是不會有延遲,較為安全(尤其是在多執行緒的環境下)。所以,通過 const_cast 改變的記憶體可以及時反映。

但是 const_cast 並沒有改變 const 變數的 const 屬性,改變的只是原始宣告 const int data = 100 中,data 地址指向的記憶體。 const 屬性和 data 都被翻譯成機器的程式碼了,可執行程式是不可變的,其中的 const data 是已經確定了的,的確存在於暫存器中,和原來的記憶體沒有關係了 。等到學了反彙編,也許就更清楚了。