C++中提供4种显式类型转换。今天实验了其中的static_cast、const_cast、与reinterpret_cast。
static_cast转换用于比较安全的转换或者意义清晰的转换。同时可以用于显式地说明编译器自动的隐式类型转换。
//static_cast.cpp #include<iostream> using namespace std; int main(){ long int i; int b; i = b;//编译器隐式地将b转化为long类型 i = static_cast<long>(b);//此处是显式地转换 //若b处不加括号,则会报错 b = i;//此处为编译器隐式地窄化变换,可能有数据的丢失 b = static_cast<int>(i);//显式地强调一下窄化类型转换。依然可能丢失数据,但是意义更加明确 void *f = &i; int *fi = (int*)f;//这是C语言中的转换方式 fi = static_cast<int*>(f);//C++中的方式在此处与原来的方式效果相同 return 0; }
const_cast为常量转换。可以将const转换为非const,将volatile转换为非volatile(volatile:强制命令编译器从内存地址中读取变量,而非自动将其转到寄存器中)。
如果取得常量的地址,可以生成一个指向常量的指针,不用转换是不能将其赋予一个非常量的指针的。这一点在c语言中没有限制。因此C++更加安全。看下面两个例子。
//const_cast.cpp #include<iostream> #include<cstdlib> using namespace std; int main(){ const int c = 10; int *j = const_cast<int*>(&c); //int i = const_cast<int>(c); //报错:invalid use of const_cast with type `int', //which is not a pointer, reference, nor a pointer-to-data-member type //因此const_cast只能用于指针转换 *j = 2;//并没有改变c的值 ,若c为全局变量,会导致程序崩溃 cout<<c<<" "<<*j<<endl; cout<<&c<<" "<<j<<endl;//有意思的现象 system("pause"); return 0; }
//const_cast.c #include<stdio.h> #include<stdlib.h> int main(){ const int c = 10; int* i = &c; *i = 2; printf("%d\t%d\n",c,*i); system("pause"); return 0; }
reinterpret_cast修改了操作数的类型,但并没有改变内存单元中的二进制编码。因此该操作十分危险。除非必要情况,减少使用。此处引用《Thinking in C++》中的例子。
//reinterpret.cpp #include<iostream> using namespace std; const int sz = 100; struct X { int a[sz]; };//结构X只包含一个整型数组 void print(X* x){ for(int i = 0; i < sz ; i++) cout<<x->a[i] << ' ';//将x中的数组中的每一个元素都打印出来 cout << endl <<"-------------------"<<endl; } int main(){ X x; print(&x);//此处打印的数字为没有意义的随机数 int* xp = reinterpret_cast<int*>(&x); for(int* i=xp; i < xp + sz; i++) *i = 0; //不能将xp当做X指针来用。除非你将它转换回X类型 print(reinterpret_cast<X*>(xp)); //以下操作可以得到同样效果 print(&x); return 0; }