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

reinterpret_cast <new_type> (expression)

reinterpret_cast运算符是为此来处理无关类型之间的变换;它见面产生一个新的值,这个值会有同原来参数(expressoin)有完全相同的于特位。

哟是无关类型?我尚未作明白,没有找到好之文档来说明类型之间到底都发生来什么关联(除了类的累以外)。后半词也看出了reinterpret_cast的字面意思:重新诠释(类型的可比特位)。我们实在可以擅自拿一个类型值的比较特位交给其他一个品类作为其的值吗?其实不然。

IBM的C++指南里倒明确告知了咱们reinterpret_cast可以,或者说应该在啊地方用来当转换运算符:

  • 于指针类型到一个够好之平头类型
  • 自打整数类型或者枚举类型到指针类型
  • 从一个对函数的指针到外一个两样品类的指向函数的指针
  • 打一个对对象的指针到另外一个异品种的对对象的指针
  • 自打一个对准类函数成员的指针到其他一个针对性不同品类的函数成员的指针
  • 由一个指向类数据成员的指针到任何一个对不同品种的数据成员的指针

但我于Xcode中测试了转,事实上reinterpret_cast的施用并无囿于在上面所说的几乎起的,任何类型的指针之间都得互相转换,都不见面赢得编译错误。上述列有底几乎件,可能
是Linux下reinterpret_cast使用的克,也或是IBM推荐我们使用reinterpret_cast的方式

于是总来说:reinterpret_cast用在任意指针(或引用)类型中的换;以及指针与足够大的整数类型中的变;从整数类型(包括枚举类型)到指针类型,无视大小。

(所谓”足够大的平头类型”,取决于操作系统的参数,如果是32各类的操作系统,就得整形(int)以上之;如果是64各的操作系统,则最少需要长整形(long)。具体大小可以经过sizeof运算符来查看)。

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将一个整型的地方转换成为该函数类型并赋值给了对应的变量。最后,我还用该整形变量作为参数交给了依靠为函数的指针变量。

此历程编译器都成功之编译通过,不过要运行我们虽会拿走”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
*扩展性也是均等大高的),唯一损失的或许就是存取的时候整形和地方的换(这全然可以忽略不计)。

然而可读性可能就无愈,所以在这种景象下使用的时光,就足以用typedef来定义个指针类型:
typedef unsigned int PointerType;

然不是重复棒,当我们以64号机器上运行的时候,只要反化:
typedef unsigned long PointerType;

当reinterpret_cast面对const

IBM的C++指南指出:reinterpret_cast不能像const_cast那样去除const修饰符。
这是什么意思为?代码还是最好直观的发挥:

int main() 
{
    typedef void (*FunctionPointer)(int);
    int value = 21;
    const int* pointer = &value;

    //int * pointer_r = reinterpret_cast<int*> (pointer); 
    // Error: reinterpret_cast from type 'const int*' to type 'int*' casts away constness

    FunctionPointer funcP = reinterpret_cast<FunctionPointer> (pointer);
}

事例里,我们比如说前const_cast一篇选至之例子那样,希望将针对const的指针用运算符转换成非指向const的指针。但是当实用reinterpret_cast的时刻,编译器直接报错组织了该过程。这就是反映出了const_cast的特有之处。

然,例子中还有一个移是拿对const
int的指针付给指向函数的指针,编译顺利经编译,当然结果吧会暨前面的例子一样是空虚的。

若我们换一种角度来拘禁,这不啻为是理所当然的。因为
const int* p = &value;int * const q = &value;

当即简单只报告句子之义是不同的,前者是”所因内容不可变”,后者则是”指向的地点不可变”(切切实实参考此处)。因此对函数的指针默认应该就是包含”所依内容不可变”的特点。

总归函数在编译之后,其操作过程就一定于那边了,我们唯一能够开的尽管是传递一些参数为指针,而望洋兴叹转移就编译函数的过程。所以打这角度来想,上边例子使用reinterpret_cast从const
int * 到FunctionPointer转换就变换得在理了,因为其并没去const限定

Director: Jim
Fawcett

  1. C++ Language Tutorial – Type
    Casting
  2. Object Oriented
    Design
  3. IBM Complilers – XL C/C++ V9.0 for Linux – The reinterpret_cast
    operator (C++
    only)
  4. Bjarne Stroustrup’s C++ Style and Technique
    FAQ
  5. MSDN Visual C++ Developer Center – reinterpret_cast
    Operator

相关文章