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上的例子:
#include
<iostream
>
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
;
}
这段代码适合体现哈希的思想,暂时不做深究,但至少看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;
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限定
相关推荐
其中,const_cast和reinterpret_cast运算符在进行类型转换时扮演了关键的角色。本文将详细介绍const_cast和reinterpret_cast的用法和适用场景。 首先,const_cast运算符主要用于去除指针或引用的const、volatile和_...
使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast。 const_cast,字面上理解就是去const属性。 static_cast,命名上理解是静态类型转换。如int转换成char。 dynamic_cast,...
C++ 提供了四个显式的数据类型转换函数:reinterpret_cast、const_cast、static_cast 和 dynamic_cast。这些转换函数可以在编译期间或运行期间实现数据类型的转换。 1.reinterpret_cast reinterpret_cast 是一种低...
C++类型转换运算符的实例详解 C++中有4个类型转换运算符,使装换过程更规范 dynamic_cast; const_cast; static_cast; reinterpret_cast; 一、dynamic_cast 该运算符我在之前的文章中已经介绍过了 //...
C++提供了四种标准的强制类型转换运算符,分别是`static_cast`、`dynamic_cast`、`reinterpret_cast`和`const_cast`。这些运算符在不同的情景下有不同的用途和限制,下面我们逐一详细探讨。 1. `static_cast` `...
`static_cast`适用于执行标准类型间的转换,包括数值类型之间的转换、指针或引用的向上转型、使用单参数构造函数的转换以及使用转换运算符的转换。`static_cast`不会进行运行时检查,因此如果转换不适当,可能导致...
本文详细介绍了C++中的四个用与强制类型转换的运算符:用来修改类型的const 或volatile 属性的const_cast,用来修改操作数类型的reinterpret_cast,static_cast,dynamic_cast
10. `reinterpret_cast` reinterpret 类型转换运算符 11. `new` 创建动态内存对象运算符 12. `delete` 释放对象运算符 13. `delete[]` 释放数组运算符 14. `noexcept` 能否抛出异常运算符 15. `sizeof` 对象大小...
`强制类型转换.cpp`可能包含对C++的静态和动态类型转换的探讨,包括`static_cast`、`dynamic_cast`、`reinterpret_cast`和`const_cast`,这些都是C++中处理多态性和类型安全的关键工具。 `.exe`文件是编译后的可...
显式类型转化(如`static_cast`,`dynamic_cast`,`reinterpret_cast`,`const_cast`)则由程序员手动指定,用于更精确地控制类型转换过程。 以下是一些关于类型转化的例子: ```cpp int i = 5; double d = i; // ...
C++提供了多种强制类型转换运算符,如`static_cast`、`dynamic_cast`、`reinterpret_cast`和`const_cast`。这些运算符用于在不同类型的对象间进行显式转换,以实现编译时或运行时的类型转换。其中,`static_cast`常...
2. 显式类型转换:包括`static_cast`、`dynamic_cast`、`reinterpret_cast`和`const_cast`。在运算符重载中,`static_cast`常用于类型转换,尤其是在多态类型和指针之间。 五、注意事项 1. 避免在不明确的情况下...
在强制类型转换方面,C++引入了C风格的类型转换,如(int*),同时提供了更安全的静态类型转换(static_cast)、const_cast、dynamic_cast和reinterpret_cast。这些转换允许开发者明确指定如何进行类型之间的转换,降低...
在C++中,静态类型转换(Static_cast)、动态类型转换(Dynamic_cast)、常量转换(Const_cast)、重新解释类型转换(Reinterpret_cast)是四种类型转换操作符,各自有着不同的作用和使用环境。例如,Static_cast...
- **标准转换序列**:包括整数提升、浮点数到整数的转换、函数调用时的参数匹配等。 - **算术转换**:在运算符操作数之间自动进行,例如将char或short转换为int进行运算。 - **列表初始化**:在C++11中引入,允许...
在C++中,static_cast和reinterpret_cast是两种常用的类型转换运算符。static_cast用于类层次结构中类型之间的转换,如向上转型(派生类转基类)和向下转型(基类转派生类),以及非多态类型之间的转换。例如,可以...
- C++引入了新的类型转换运算符,如 `static_cast<>`、`dynamic_cast<>`、`const_cast<>` 和 `reinterpret_cast<>`。这些运算符旨在提供更安全、更清晰的类型转换方式。由于它们是C++语言的关键部分,因此不允许被...
### C和C++运算符优先级详解 在编程语言中,理解运算符的优先级是至关重要的,因为这直接影响到表达式的计算顺序和结果。C和C++作为两种广泛使用的编程语言,它们共享大部分相同的运算符及其优先级规则,但也有细微...
在C++中,还有一种传统的强制类型转换方式,如`(type)expression`,虽然在某些情况下仍然可用,但现代C++推荐使用`static_cast`、`const_cast`、`dynamic_cast`和`reinterpret_cast`,因为它们提供了更明确的语义和...