C++ 学习笔记(3) const_cast

const_cast

C++的四种类型转换关键字之一, const_cast , static_cast , dynamic_cast, reinterpret_cast 。

不可以去除一个 const 变量的 const 属性。可以跨过 const 访问原始变量( 和 const 变量不同 )。

很容易理解错的一个例子:

#include 
using namespace std ;

int main () {
	const int data = 100 ;
	int *p = const_cast( &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

C++ 学习笔记(3) const_cast_第1张图片

很奇怪? data 的地址是 0x6ffe34, p 指向的地址也是 0x6ffe34, 但是修改 p 之后, 同一个地址上的内容却不相同。

可能是 const 的问题? const 的机制,就是在编译期间,用一个常量代替了 data。

关键在这里:

#include 
using namespace std ;

int main () {
	const int volatile data = 100 ;
	int *p = const_cast( &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 。

C++ 学习笔记(3) const_cast_第2张图片

可以注意到,程序的差别就在一个 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 是已经确定了的,的确存在于寄存器中,和原来的内存没有关系了 。等到学了反汇编,也许就更清楚了。



你可能感兴趣的:(c++)