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

reinterpret_cast <new_type> (expression)

reinterpret_cast运算符是用来拍卖无关类型之间的变换;它会发出七个新的值,那些值会有与原本参数(expressoin)有完全相同的比特位。

如何是无关类型?小编并未弄领会,没有找到好的文书档案来表明类型之间到底都有些什么关系(除了类的三番八次以外)。后半句倒是看出了reinterpret_cast的字面意思:重新解释(类型的比特位)。大家确实能够肆意将八个类型值的比特位交给另二个连串作为它的值吗?其实不然。

IBM的C++指南里倒是显明告诉了大家reinterpret_cast能够,可能说应该在怎么着地方用来作为转换运算符:

  • 从指针类型到3个足够大的整数类型
  • 从整数类型或许枚举类型到指针类型
  • 从3个针对函数的指针到另五个见仁见智品种的针对性函数的指针
  • 从二个对准对象的指针到另二个不一品类的针对性对象的指针
  • 从二个针对类函数成员的指针到另多个对准不相同类别的函数成员的指针
  • 从1个指向类数据成员的指针到另二个针对性分歧品种的多寡成员的指针

只是笔者在Xcode中测试了一下,事实上reinterpret_cast的使用并不局限在上边所说的几项的,任何项指标指针之间都得以互相转换,都不会博得编写翻译错误。上述列出的几项,也许是Linux下reinterpret_cast使用的界定,也只怕是IBM推荐大家选择reinterpret_cast的方式

为此计算来说:reinterpret_cast用在随机指针(或引用)类型之间的更换;以及指针与丰硕大的整数类型之间的变换;从整数类型(包蕴枚举类型)到指针类型,无视大小。

(所谓”丰硕大的平头类型”,取决于操作系统的参数,假诺是三十一位的操作系统,就必要整形(int)以上的;倘诺是六1伍人的操作系统,则最少须要长整形(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定义了一个针对函数的指针类型,所针对的函数接受2个int类型作为参数。然后小编用reinterpret_cast将3个整型的地方转换到该函数类型并赋值给了相应的变量。最终,我还用该整形变量作为参数交给了指向函数的指针变量。

本条历程编写翻译器都成功的编写翻译通过,但是要是运转大家就会得到”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;

这般不是更棒,当大家在61位机器上运行的时候,只要改成:
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

相关文章