C++学习笔记:数据类型相关typeid、cast、自动类型推导

C++是强类型语言,里面的每一个变量和表达式都有自己的类型。有了类型编译器就可以帮助进行类型检查,有错误就会报出来。

1.typeid

typeid是一个运算符,用来返回一个变量(或者表达式、对象)的类型。typeid定义在头文件typeinfo中,因此使用的时候必须包含该头文件。使用语法是:

typeid(e);

举个栗子:

#include<iostream>
#include<typeinfo>

using namespace std;

class person
{
};
int main(int argc,char**argv)
{
	int a = 10;
	short b;
	char c;
	person d;
	cout<<"type of int a = "<<typeid(a).name()<<endl;
	cout<<"type of short b = "<<typeid(b).name()<<endl;
	cout<<"type of char c = "<<typeid(c).name()<<endl;
	cout<<"type of person d = "<<typeid(d).name()<<endl;
	
	cout<<"type of typeid(a) = "<<typeid(typeid(a)).name()<<endl;
	
	return 0;
}

输出:

type of int a = i
type of short b = s
type of char c = c
type of person d = 6person
type of typeid(a) = N10__cxxabiv123__fundamental_type_infoE

typeid的深层次说明:

  • 1.一个表达式的类型分静态类型(在编译器编译的时候就可以确定类型,大部分类型都是静态的,比如intdouble等)和动态类型(这个符号在运行的时候才能确定具体的类型,比如void*),分别对应编译期和运行时类型决策系统。
  • 2.typeidC++语言本身的特性,由编译器和库函数共同支撑。
  • 3.typeid可用来返回静态类型,也可用来返回动态类型,它真正大用在运行时的动态类型检查。在引入类和继承后,并结合指针和引用后才能显现出来。

2.C++中的4中cast

2.1 静态转换static_cast

源生类型之间的隐式类型转换,可以用static_cast来明确告知编译器,避免警告,转换后可能丢失精度,因此转换的正确性需要程序员自己保证。

举个栗子:

int main(int argc,char**argv)
{
	int a = 88;
	//char c = a;
	char c = static_cast<char>(a);
	cout<<c<<endl;
	return 0;
}

输出:

X

static_cast还用来将void*类型的指针转为具体的指针类型,取回原有的指针类型。

举个栗子:

int main(int argc,char**argv)
{
	int a = 88;
	int* p1 = &a;
	void* p2 = p1;	//此时p2已经丢失了指针类型
	int* p3 = static_cast<int*>(p2);	//p3取回了类型
	cout<<*p3<<endl;
	return 0;
}

输出:

88

static_cast也用于类层次结构中父类和子类之间指针和引用的转换,其中上行转换时安全的,而下行转换时不安全的。

总结:static_cast<>()是编译时静态类型检查,使用static_cast可以尽量发挥编译器的静态类型检查功能,但是并不能保证代码一定“正确”(譬如可能会丢失精度导致错误,可能经过void *之后导致指针类型错误,可能下行转换导致访问错误)。static_cast实际上只能解决很初级的编程问题,属于初级语法特性。

2.2 重新解释转换reintepret_cast

reintepret_cast用于明确告知编译器该类型转换在编译时放行,正确性由程序员自己负责。reintepret_cast转换前后对象(变量)在内存中的二进制数据并未发生任何变化,只是对这些二进制位的编译器类型标识发生了变化,或者说是编译器对这些二进制位的解析方式不同了。

reintepret_cast一般用于将指针转成int或者回转,将A类型指针转为B类型指针等,它其实就是让C++在本次转换中放弃严苛的编译器类型检查。

2.3 const_cast

cconst_cast用来修改类型的constvolatile属性。

int main(int argc,char**argv)
{
	const int a = 5;
	// a=6; 编译报错

	int* p=const_cast<int*>(&a);
	*p=14;
	cout<<*p<<endl;
	return 0;
}

思考:const_cast为什么能修改const为非const?因为const变量不是物理上(将变量写在只读内存区)实现的,而是编译的时候由编译器保证不被修改的。

2.4 动态转换dynamic_cast

dynamic_cast只用在父子class的指针和引用访问时的转换中,尤其是下行转换时。dynamic_cast属于一种运行时转换机制,运行时才能知道转换结果是NULL(转换失败返回)还是有效对象(转换成功返回)。运行时确定对象类型RTTI(run time type indentification)是一种需求,C++有一套机制来实现。

4种cast转换总结:C语言中一般都用隐式转换或强制类型转换解决,本质上是一种一刀切方案,全靠程序员自己把控。C++中4种cast转换实际上是细分了具体场景,让程序员在具体情况下显式的使用相应的cast来转换,让编译器和运行时尽可能帮程序员把关。

3.C++的自动类型推导

3.1 auto关键字

autoC中修饰局部变量,可以省略,完全无用。C++中的auto完全是一个新关键字,要求至少不低于C++11标准来支撑。

auto在编译器由编译器帮我们自动推导出变量(对象)类型,所以定义时必须初始化,auto可以一次定义多个同类型的变量,但是不能一次定义多个类型不同的变量,这是auto的类型推导机制决定的。

auto i = 5;
//则i被自动推导为int类型

auto a=4,b=5; 	//可以
auto x=4,y=5.5;	//不可以

3.2 decltype关键字

decltypeC++11新增关键字,可以让编译器推导目标表达式的类型作为一种类型符使用。decltype(表达式)作为类型定义变量不要求初始化。

int i =5;
decltype(i) j;
//则j的类型同i,是int类型

3.3 auto和decltype的对比

  • 1.auto忽略顶层const,而decltype则保留const
  • 2.auto作为类型占用符,而decltype用法类似于sizeof运算符。
  • 3.对引用操作,auto推断出原有类型,decltype推断出引用。
  • 4.对解引用操作,auto推断出原有类型,decltype推断出引用。
  • 5.auto推断时会实际执行,decltype不会执行,只做分析。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值