C++11 reinterpret_cast讲解

50 篇文章 0 订阅
32 篇文章 0 订阅
本文详细解释了C++中的reinterpret_cast,一种特殊的类型转换,用于指针和不同类型间的转换。讨论了其使用场景,包括内存地址保持、垃圾回收的潜在问题以及在跨语言交互(如JNI与OpenCV)中的应用。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

我觉得C++里面有一个很神奇的转换叫reinterpret_cast(类型不相关转换),它和诸如static_cast、dynamic_cast都不一样,这种转换有时候让人摸不到头脑,但是有些场景非常有用。


一、什么是reinterpret_cast

简而言之,类型不相关的转换。但是不是说可以随便转换,它主要用在指针与指针之间,指针和long之间等等。必要条件是两种类型之间必须有相同的位模式,而且转换过后不能直接拿来用,必须转换回来才能使用。

二、代码测试

//返回转换结果,long型
long test_reinterpret_cast() {
    int *a = new int{2};
    long b = reinterpret_cast<long>(a);
    return b;
}

int main(){
	 long b = test_reinterpret_cast();
    int *c = reinterpret_cast<int *>(b);
    cout << "c = " << *c << endl;
    delete c;
	return 0;
}

注意上面的方法,按照平常的写法是不是就memory leak了。很多聪明的IDE会提示你int* a这个地方内存泄漏了,事实真的如此吗?

这就不得不说reinterpret_cast的强大之处了,因为b和a拥有相同的位模式,所以转换是有效的。当我把b转换回a(或c,其实就是内存地址)的时候我又重新指向new出来的内存了,这个时候delete c就回收内存了。使用valgrind测试,没有出现内存溢出的情况。

注意:如果把b换成int类型就不行了,int类型和int*在64bits系统上没有相同的位模式,因为int*在64bits系统上占8个字节,int在64bits系统上占4个字节,所以会报错,long型在64bits系统上也占8个字节。

三、垃圾回收器的困扰

可能很多人不知道C++其实预留了垃圾回收接口,不过实现起来很复杂,还可能会出现意想不到的情况。比如上面的reinterpret_cast就可能成为阻挠垃圾回收的罪魁祸首。我们回过头来再看下上面的代码:

//返回转换结果,long型
long test_reinterpret_cast() {
    int *a = new int{2};
    long b = reinterpret_cast<long>(a);
    return b;
}

int main(){
	 long b = test_reinterpret_cast();
    int *c = reinterpret_cast<int *>(b);
    cout << "c = " << *c << endl;
    delete c;
	return 0;
}

return b;之后就没有指针指向int* a所指向的内存地址了,按道理说是不是这块内存要被垃圾回收器回收了。现实是我们保存在long b里面了,垃圾回收器并不知道,还是照样回收。等到代码执行到int *c = reinterpret_cast<int *>(b);这句的时候,是不是转换结果就失效了。这个时候强行访问这块内存就会报非法内存错误

四、使用场景

不说C++源代码到处是reinterpret_cast了,好不好用还有谁比专家更清楚。

除了这些还有其它场景,如果你看过诸如Android操作系统源代码OpenCV的源代码你就会知道,reinterpret_cast用的简直不要太多。我举一个例子你就懂了,我们都知道OpenCV为了获得高性能底层大量使用C++开发。如果你在Java层使用OpenCV它是不是要调用C++层的东西,我们都知道JNI就是这个桥梁。但是,如果我问题你怎么完成Java对象和C++对象之间的传递和转换呢?Java对象和C++对象可是拥有着不同的内存结构的,难道你要跨语言转换对象吗?

聪明的开发者已经想到了,当然是用我们的reinterpret_cast了,我可以把C++的对象转换成long型传回Java层,这个long你可以理解为就是指向C++层创建的对象的内存地址,等到合适的时机我把它转换回来就行了。然后Java层也创建一个Java对象里面保存long、rows、cols等等必要的消息,只有需要运算的时候我才把long传下去转换,只需要很小的代价这就解决了这个问题,比起巨大的性能提升这点内存还是微不足道的。

由于C++是手动回收内存的,你永远不必担心这块内存会丢失,直到你不再需要它为止。


总结

1、研究了很久还是决定拿出来掰扯掰扯。

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值