CPP基础--表达式之类型转换

由 adtxl 发布

类型转换

何时发生隐式类型转换
在下面这些情况下,编译器会自动地转换运算对象的类型:

  • 在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型。
  • 在条件中,非布尔值转换成布尔类型
  • 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型
  • 如果算术运算关系或关系运算的运算对象有多种类型,则需要转换成同一种类型。
  • 函数调用时也会发生类型转换

1. 算术转换

算术转换的含义是把一种算术类型转换成另外一种算术类型。

2. 其他隐式类型转换

数组转换成指针
在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针:

int ia[10];     // 含有10个整数的数组
int* ip = ia;   // ia转换成指向数组首元素的指针

当数组被用作decltype关键字的参数,或者作为取地址符(&)、sizeof及typeid等运算符的运算对象时,上述转换不会发生。同样的,如果用一个引用来初始化数组,上述转换也不会发生。

指针的转换
C++还规定了其他的指针转换方式,包括常量整数值0或者字面值nullptr能转换成任意指针类型;指向任意非常量的指针能转换成void*;指向任意对象的指针能转换成const void*。

转换成布尔类型
存在一种从算术类型或指针类型向布尔类型自动转换的机制。如果指针或算术类型的值为0,转换结果是false;否则转换结果是true

转换成常量
允许将指向非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样。

3. 显式转换

有时我们希望显式地将对象强制转换成另外一种类型。例如,如果想在下面的代码中执行浮点数除法;

int i, j;
double slope = i/j;

就要使用某种方法将i或j显式地转换成double,这种方法称作强制类型转换(cast)。
注:虽然有时不得不使用强制类型转换,但这种方法本质上是非常危险的。

  • 命名的强制类型转换

一个命名的强制类型转换具有如下形式:

cast-name<type>(expression);

其中,type是转换的目标类型,而expression是要转换的值。如果type是引用类型,则结果是左值。
cast-name是static_castdynamic_castconst_castreinterpret_cast中的一种。cast-name指定了执行的是哪种转换。

static_cast

任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast。

// 进行强制类型转换以便执行浮点数除法
double slope = static_cast<double>(j) / i;

static_cast对于编译器无法自动执行的类型转换也非常有用。例如,我么可以使用static_cast找回存在于void*指针中的值:

void* p = &d;       // 正确:任何非常量对象的地址都能存入void*
// 将void*转换回初始的指针类型
double *dp = static_cast<double*>(p);

const_cast

const_cast只能改变运算对象的底层const

const char *pc;
char *p = const_cast<char*>(pc);    //正确,但是通过p写值是未定义的行为

对于将常量对象转换成非常量对象的行为,我们一般称其为“去掉const性质”。一旦我们去掉了某个对象的const性质,编译器就不能再阻止我们对该对象进行写操作了。如果对象本身不再是一个常量,使用强制类型转换获得写权限是合法的行为。然而如果对象是一个常量,再使用const_cast执行写操作就会产生未定义的后果。
只有const_cast能改变表达式的常量属性,同样,const_cast不能用来改变表达式的类型。
const_cast常常用于有函数重载的上下文中。

reinterpret_cast

reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释。
建议:避免强制类型转换,尤其是reinterpret_cast


暂无评论

发表评论