【转】C++标准转换运算符reinterpret_cast

reinterpret_cast<new_type> (expression)

reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expression)有彻底相同的比特位。html

什么是无关类型?我没有弄清楚,没有找到好的文档来讲明类型之间到底都有些什么关系(除了类的继承之外)。后半句却是看出了reinterpret_cast的字面意思:从新解释(类型的比特位)。咱们真的能够随意将一个类型值的比特位交给另外一个类型做为它的值吗?其实否则。ios

IBM的C++指南里却是明确告诉了咱们reinterpret_cast能够,或者说应该在什么地方用来转换运算符:express

  • 从指针类型到一个足够大的整数类型
  • 从整数类型或者枚举类型到指针类型
  • 从一个指向函数的指针到另外一个不一样类型的指向函数的指针
  • 从一个指向对象的指针到另外一个不一样类型的指向对象的指针
  • 从一个指向类函数成员的指针到另外一个指向不一样类型的函数成员的指针
  • 从一个指向类数据成员的指针到另外一个指向不一样类型的数据成员的指针

不过我在Xcode中测试了一下,事实上reinterpret_cast的使用并不局限在上边所说的几项的,任何类型的指针之间均可以互相转换,都不会获得编译错误。上述列出的几项,可能 是Linux下reinterpret_cast使用的限制,也多是IBM推荐咱们使用reinterpret_cast的方式。安全

因此总结来讲:reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。jsp

(所谓“足够大的整数类型”,取决于操做系统的参数,若是是32位的操做系统,就须要整型(int)以上的;若是是64位的操做系统,则至少须要长整型(long)。具体大小能够经过sizeof运算符来查看)。ide

reinterpret_cast有何做用

从上边对reinterpret_cast介绍,能够感受出reinterpret_cast是个很强大的运算符,由于它能够无视种族隔离,随便搞但就像生物的准则,不符合天然规律的随意杂交只会获得不能长久生存的物种。随意在不一样类型之间使用reinterpret_cast,也会形成程序的破坏和不能使用函数

好比下边的代码测试

typedef int (*FunctionPointer)(int); 
int value = 21; 
FunctionPointer funcP; 
funcP = reinterpret_cast<FunctionPointer> (&value); 
funcP(value); 

先用typedef定义一个指向函数的指针类型,所指向的函数接受一个int类型做为参数。而后我用reinterpret_cast将一个整型的地址转换成该函数类型并赋值给了相应的变量。最后,我还用该整型变量做为参数交给了指向函数的指针变量。spa

这个过程编译器都成功地编译经过,不过一旦运行咱们就会获得“EXC_BAD_ACCESS”的运行错误,由于咱们经过funcP所指的地址找到的并非函数入口。操作系统

由此可知,reinterpret_cast虽然看似强大,做用却没有那么广。IBM的C++指南、C++之父Bjarne Stroustrup的FAQ网页MSDN的Visual C++也都指出:错误的使用reinterpret_cast很容易致使程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。

这样提及来,reinterpret_cast转换成其它类型的目的只是临时地隐藏本身的什么(作个卧底?),要真想使用那个值,仍是须要让其露出真面目才行。那到底它在C++中有其怎样存在的价值呢?

MSDN的Visual C++ Developer Center 给出了它的使用价值:用来辅助哈希函数。下边是MSNDN上的例子:

// expre_reinterpret_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>
// Returns a hash code based on an address
unsigned short Hash( void *p ) {
    unsigned int val = reinterpret_cast<unsigned int>( p );
    return ( unsigned short )( val ^ (val >> 16));
}

using namespace std;
int main() {
    int a[20];
    for ( int i = 0; i < 20; i++ )
        cout << Hash( a + i ) << endl;
}

//若是跟我同样是64位的系统,可能须要将unsigned int改为 unsigned long才能运行。

 

这段代码是如何体现哈希的思想,暂时不作深究,但至少看Hash函数里面的操做,也能体会到,对整数的操做显然要比对地址操做更方便。在集合中存放整型数值,也要比存放地址更具备扩展性(固然若是存void *扩展性也是同样很高的),惟一损失的可能就是存取的时候整型和地址的转换(这彻底能够忽略不计)。

 

转自:

http://www.cnblogs.com/ider/archive/2011/07/30/cpp_cast_operator_part3.html

相关文章
相关标签/搜索