在C++语言中,某些类型之间有关联。如果两种类型有关联,那么当程序需要其中一
种类型的运算对象时,可以用另一种关联类型的对象或值来替代。换句话说,如果两种类
型可以相互转换(conversion),那么它们就是关联的。
例子:
int ival = 3.125+6;
因为3.125是double类型,所以先将6转化为double类型,执行浮点型运算得到 9.125
再将9.125转化为int型赋值给 ival
隐式类型转换
C++不会直接将两个不同类型的值相加,而是先根据类型转换规则设法将运算对象的类型统一后再求值。
上述的类型转换是自动执行的,无须程序员的介入,有时甚至不需要程序员了解。因此,它们被称作隐式转换(implicit conversion)。
算术类型之间的隐式转换被设计得尽可能避免损失精度。很多时候,如果表达式中既有整数类型的运算对象也有浮点数类型的运算对象,整型会转换成浮点型。
何时发生隐式类型转换 ?
在下面这些情况下,编译器会自动地转换运算对象的类型:
- 在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型。
- 在条件中,非布尔值转换成布尔类型。
- 初始化过程中,初始值转换成变量的类型
- 在赋值语句中,右侧运算对象转换成左侧运算对象的类型。
- 如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。
- 如第6章将要介绍的,函数调用时也会发生类型转换。
数组和指针
通常情况下 数组名字 约等于 指向数组首元素的指针
string nums[] ={ "one" ,"two" , "three"};
string *p = &nums[0];
string *p2 = &nums;
在这里 *p
和 *p2
是等价的
auto 和 decltype的区别
假设
int ia[]={0,1,2,3};
auto ia2(ia);//1
auto ia2(&ia[0]);//2
ia2的类型是 int*,编译器执行代码1 实际上执行的是代码2
而decltype(ia) 返回的是有4个元素的数组
对数组执行sizeof运算得到整个数组所占空间的大小,等价于对数组中所有的元素各执行一次sizeof运算并将所得结果求和。注意,sizeof运算不会把数组转换成指针来处理。
指针的转换
- 常量整数值0或者字面值nullptr能转换成任意指针类型
- 指向任意非常量的指针能转换成void*:
- 指向任意对象的指针能转换成const void*
显示转换
cast-name(expression);
type是转换的目标,expression是要转换的值。如果type是引用类型,则结果是左值
cast-name 的取值范围有
static_cast
任何具有明确定义的类型转换,只要不包含底层const,都可以使用。常见用法:
- 把一个较大的算术类型赋值给较小的类型
int i=635,j=544;
double slope = static_cast<double>(j)/i;
当需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用。此时,强制类型转换告诉程序的读者和编译器:我们知道并且不在乎潜在的精度损失。一般来说,如果编译器发现一个较大的算术类型试图赋值给较小的类型,就会给出警告信息:但是当我们执行了显式的类型转换后,警告信息就会被关闭了。
- 指针
double d;
void* p =&d;//正确:任何非常量对象的地址都可以存入 void*
double *dp = static_cast<double*>(p);
当我们把指针存放在void*中,并且使用 static_cast 将其强制转换回原来的类型时,应该确保指针的值保持不变。也就是说,强制转换的结果将与原始的地址值相等,因此我们必须确保转换后所得的类型就是指针所指的类型。类型一旦不符,将产生未定义的后果。
补充说明:
顶层const:表示指针本身是一个常量
底层const:表示指针所指向的对象是一个常量
int i=0;
int *const pl =&i;// 顶层const 不能改变pl的值
const int ci =42; // 顶层const 不能改变ci的值
const int *p2 = &ci ; //允许改变p2的值,底层const
*const
常量指针
const *
指向常量
const_cast
将常量对象转换成非常量对象,去掉const的性质
const char *pc;
char *p = const_cast<char*>(cp); //正确
static_cast<char*>(cp);//错误 static_cast 不能转换掉const的性质
static_cast<string>(cp);//正确 字符串字面值剋转化为string类型
reinterpret_cast
#include <iostream>
using namespace std;
int main()
{
// 16进制表示
int num = 0x00636261;
// 用int类型指针指向num
int* p_int = #
// 将int类型的指针转换为char类型的指针
char* p_char = reinterpret_cast<char *>(p_int);
// 输出结果
cout<<"p_int的值:" << p_int <<endl;
cout<<"p_char的值: "<< static_cast<void *>(p_char)<<endl;// 为了输出p_char的值而进行类型转换(不然会输出其指向的字符串)
cout<<"p_int指向的内容: " << hex <<*p_int<<endl;
cout<<"p_char指向的内容: "<< p_char <<endl;
return 0;
}
p_int 和p_char 指向同一片内存,即num 所在的地方。
但是解引用之后, p_int 会按照int类型读取这片内存, p_char 则是按照 char的方式。所以输出不一样