详解C++中const_cast与reinterpret_cast运算符的用法

const_cast 运算符
从类中移除 const、volatile 和 __unaligned 特性。
语法

const_cast <
type-id
 > (
expression
 )

备注
指向任何对象类型的指针或指向数据成员的指针可显式转换为完全相同的类型(const、volatile 和 __unaligned 限定符除外)。对于指针和引用,结果将引用原始对象。对于指向数据成员的指针,结果将引用与指向数据成员的原始(未强制转换)的指针相同的成员。根据引用对象的类型,通过生成的指针、引用或指向数据成员的指针的写入操作可能产生未定义的行为。
您不能使用 const_cast 运算符直接重写常量变量的常量状态。
const_cast 运算符将 null 指针值转换为目标类型的 null 指针值。

// expre_const_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class CCTest {
public:
  void setNumber( int );
  void printNumber() const;
private:
  int number;
};

void CCTest::setNumber( int num ) { number = num; }

void CCTest::printNumber() const {
  cout << "\nBefore: " << number;
  const_cast< CCTest * >( this )->number--;
  cout << "\nAfter: " << number;
}

int main() {
  CCTest X;
  X.setNumber( 8 );
  X.printNumber();
}

在包含 const_cast 的行中,this 指针的数据类型为 const CCTest *。 const_cast 运算符会将 this 指针的数据类型更改为 CCTest *,以允许修改成员 number。强制转换仅对其所在的语句中的其余部分持续。

reinterpret_cast 运算符
允许将任何指针转换为任何其他指针类型。也允许将任何整数类型转换为任何指针类型以及反向转换。
语法

reinterpret_cast < type-id > ( expression )

备注

  • 滥用 reinterpret_cast 运算符可能很容易带来风险。除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。
  • reinterpret_cast 运算符可用于 char* 到 int* 或 One_class* 到 Unrelated_class* 之类的转换,这本身并不安全。
  • reinterpret_cast 的结果不能安全地用于除强制转换回其原始类型以外的任何用途。在最好的情况下,其他用途也是不可移植的。
  • reinterpret_cast 运算符不能丢掉 const、volatile 或 __unaligned 特性。有关移除这些特性的详细信息,请参阅 const_cast Operator。
  • reinterpret_cast 运算符将 null 指针值转换为目标类型的 null 指针值。
  • reinterpret_cast 的一个实际用途是在哈希函数中,即,通过让两个不同的值几乎不以相同的索引结尾的方式将值映射到索引。
#include <iostream>

using namespace std;

// 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;
}

Output:

64641
64645
64889
64893
64881
64885
64873
64877
64865
64869
64857
64861
64849
64853
64841
64845
64833
64837
64825
64829

reinterpret_cast 允许将指针视为整数类型。结果随后将按位移位并与自身进行“异或”运算以生成唯一的索引(具有唯一性的概率非常高)。该索引随后被标准 C 样式强制转换截断为函数的返回类型。

(0)

相关推荐

  • 浅析c++ 中const关键字

    const是一个C++语言的限定符,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性.另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助. define与const的区别 1.define作用在预处理时,是简单地字符替换 2. const作用在编译时,具有类型检查的功能 3. const必须进行初始化 常量指针与指针常量 #include <iostream> using std::endl; using std::cout

  • 详解C/C++中const关键字的用法及其与宏常量的比较

    1.const关键字的性质 简单来说:const关键字修饰的变量具有常属性. 即它所修饰的变量不能被修改. 2.修饰局部变量 const int a = 10; int const b = 20; 这两种写法是等价的,都是表示变量的值不能被改变,需要注意的是,用const修饰变量时,一定要给变量初始化,否则之后就不能再进行赋值了,而且编译器也不允许不赋初值的写法: 在C++中不赋初值的表达一写出来,编译器即报错,且编译不通过. 在C中不赋初值的表达写出来时不报错,编译时只有警告,编译可以通过.而

  • C++ 中const和复合类型

    1.const和引用 可以把引用绑定在常量上,称之为,对常量的引用.不能对那个引用赋值. 如: const int ci = 1024; const int &ri = ci; 解读:ri是对ci的引用.ri的const意思是视ci为变量. 对于常量,只能使用"对常量的引用"这个引用方式 int &ri = ci;是错误的,因为ci不能赋值,但是可能会对ri赋值从而影响const限定. 所以,他们(制定标准的人)创造了 对常量的引用 的 引用方式. 下面高能!!! 上面

  • 详解C++中的const关键字及与C语言中const的区别

    const对象默认为文件的局部变量,与其他变量不同,除非特别说明,在全局作用域的const变量时定义该对象的文件局部变量.此变量只存在于那个文件中中,不能别其他文件访问.要是const变量能在其他文件中访问,必须显示的指定extern(c中也是)   当你只在定义该const常量的文件中使用该常量时,c++不给你的const常量分配空间--这也是c++的一种优化措施,没有必要浪费内存空间来存储一个常量,此时const int c = 0:相当于#define c 0:    当在当前文件之外使用

  • 从C语言过渡到C++之const

    1. 定义常量 1.1 C语言中定义常量的方法 在C语言从零开始这个系列中,我们讲了C语言定义常量的方法.没有看过的同学请参考:C语言从零开始(五)-常量&变量 为什么要定义常量我就不再赘述了,这里重点说说这么定义有什么不好.经常有这样的面试题:请写出下面这段代码的执行结果: #include <stdio.h> #define SUM 5 + 1; void main() { int a = 2 * SUM; printf("%d", a); } 经常有人答12,

  • C/C++中CONST用法总结(推荐)

    1.修饰常量时: const int temp1; //temp1为常量,不可变 int const temp2; //temp2为常量,不可变 2.修饰指针时: 主要看const在*的前后,在前则指针指向的内容为常量,在后则指针本身为常量: const int *ptr; //*ptr为常量: int const *ptr; //*ptr为常量: int* const ptr; //ptr为常量: const int * const ptr; //*ptr.ptr均为常量: 3.const修饰

  • C++ 中const修饰虚函数实例详解

    C++ 中const修饰虚函数实例详解 [1]程序1 #include <iostream> using namespace std; class Base { public: virtual void print() const = 0; }; class Test : public Base { public: void print(); }; void Test::print() { cout << "Test::print()" << end

  • c++ 类中const成员变量的赋值方法

    在头文件的类的定义中定义了一个const成员变量c++ 规则: 1.类定义中不能进行初始化,因为头文件中类的定义只是一个声明,并没有分配真正空间,因此变量是不存在的,因此是不能赋值的. 2.const 定义的变量是不能赋值 这可如何是好,声明中不能赋值,声明完还不能赋值.又不能不赋值. 解决方案: 1.在构造函数后的参数初始化列表中初始化 2.将const变量同时声明为 static 类型进行初始化. Eg: #include <iostream> class CTestA { public:

  • 浅析C++的引用与const指针与各种传递方式

    浅析C++的引用与const指针与各种传递方式 首先我们知道 const int *p 与 int const *p 是一样的,即 *p 是常量:而 int * const p 跟上面是不一样的,即 p 是常量:我们知道引用只是一个别名,与变量共享存储空间,并且必须在定义的时候初始化,而且不能再成为别的变量的别名,这让我们想到什么呢,貌似跟  int * const p   的性质很像. 其实引用的底层就是用const指针来实现的.下面举个小例子: #include <iostream> us

  • 详解C++中const_cast与reinterpret_cast运算符的用法

    const_cast 运算符 从类中移除 const.volatile 和 __unaligned 特性. 语法 const_cast < type-id > ( expression ) 备注 指向任何对象类型的指针或指向数据成员的指针可显式转换为完全相同的类型(const.volatile 和 __unaligned 限定符除外).对于指针和引用,结果将引用原始对象.对于指向数据成员的指针,结果将引用与指向数据成员的原始(未强制转换)的指针相同的成员.根据引用对象的类型,通过生成的指针.引

  • 详解C++中赋值,关系,函数调用运算符重载的实现

    目录 赋值运算符重载 类结构 问题的出现 具体实现 关系运算符重载 类结构 具体实现 函数调用运算符重载 类结构 具体实现 总结 赋值运算符重载 在C++中基本数据类型例如整型,可以实现连续赋值:a=b=c:而我们的对象的成员属性虽然可以相等,但是如果牵扯到堆地址,就会有深浅拷贝的问题存在.所以我们自己重载赋值运算符,实现连等的方法. 类结构 class Info { int* m_a; public: Info() { m_a = NULL; } Info(int a) { m_a = new

  • 详解Python中list[::-1]的几种用法

    本文主要介绍了Python中list[::-1]的几种用法,分享给大家,具体如下: s = "abcde" list的[]中有三个参数,用冒号分割 list[param1:param2:param3] param1,相当于start_index,可以为空,默认是0 param2,相当于end_index,可以为空,默认是list.size param3,步长,默认为1.步长为-1时,返回倒序原序列 举例说明 param1 = -1,只有一个参数,作用是通过下标访问数据,-1为倒数第一个

  • 详解PHP中的null合并运算符

    null合并运算符是一个好东西,有了它我们就能很方便的获取一个参数,并能在其为空的情况下提供一个默认值.比如在js中可以用||来搞: function setSomething(a){ a = a || 'some-default-value'; // ... } 而在PHP中,可惜PHP的||总是返回true或false,无法这样来搞.  PHP7才正式加入了??这个运算符: // 获取user参数的值(如果为空,则用'nobody') $username = $_GET['user'] ??

  • 详解JavaScript中|单竖杠运算符的使用方法

    js运算符单竖杠"|"的作用 在js整数操作的时候,相当于去除小数点,parseInt.在正数的时候相当于Math.floor(),负数的时候相当于Math.ceil() 注: 1. Math.ceil()用作向上取整. 2. Math.floor()用作向下取整. 3. Math.round() 我们数学中常用到的四舍五入取整. console.log(0.6|0)//0 console.log(1.1|0)//1 console.log(3.65555|0)//3 console.

  • 详解C++中的成员访问运算符和指针到成员运算符

    成员访问运算符:. 和 -> 语法 postfix-expression       . name postfix-expression –> name 备注 成员访问运算符 . 和 -> 用来引用结构.联合和类的成员.成员访问表达式具有选定成员的值和类型. 有两种形式的成员访问表达式: 在第一种形式中,postfix-expression 表示结构.类或联合类型的值,name 为指定的结构.联合或类的成员命名.运算的值是 name 的值且为左值(如果 postfix-expressio

  • 详解C++中赋值和输入输出语句的用法

    C++赋值语句讲解 C++的赋值语句具有其他高级语言的赋值语句的功能.但不同的是,C++中的赋值号"="是一个运算符,可以写成 a=b=c=d; 而在其他大多数语言中赋值号不是运算符,上面的写法是不合法的. 关于赋值表达式与赋值语句的概念.在C++中,赋值表达式可以包括在其他表达式之中,例如: if((a=b)>0) cout<<"a>0"<<endl; 按语法规定if后面的( )内是一个条件.现在在x的位置上换上一个赋值表达式&

  • 详解js中的apply与call的用法

    前言 call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向. call 和 apply二者的作用完全一样,只是接受参数的方式不太一样. 方法定义 apply Function.apply(obj,args)方法能接收两个参数: obj:这个对象将代替Function类里this对象 args:这个是数组或类数组,apply方法把这个集合中的元素作为参数传递给被调用的函数. call call方法与apply方

  • 详解Python中contextlib上下文管理模块的用法

    咱们用的os模块,读取文件的时候,其实他是含有__enter__ __exit__ .  一个是with触发的时候,一个是退出的时候. with file('nima,'r') as f: print f.readline() 那咱们自己再实现一个标准的可以with的类. 我个人写python的时候,喜欢针对一些需要有关闭逻辑的代码,构造成with的模式 . #encoding:utf-8 class echo: def __enter__(self): print 'enter' def __

  • 详解Java中的时区类TimeZone的用法

    一.TimeZone 简介 TimeZone 表示时区偏移量,也可以计算夏令时. 在操作 Date, Calendar等表示日期/时间的对象时,经常会用到TimeZone:因为不同的时区,时间不同. 下面说说TimeZone对象的 2种常用创建方式. 1.获取默认的TimeZone对象 使用方法: TimeZone tz = TimeZone.getDefault() 2.使用 getTimeZone(String id) 方法获取TimeZone对象 使用方法: // 获取 "GMT+08:0

随机推荐