C++11类型推导详解✍

C++的类型推导详解

auto & decltype

C++11引入了auto和decltype关键字实现类型推导,通过这两个关键字不仅能方便的获取复杂的类型,而且还能简化书写,提高编码效率。

auto :变量类型推断 & decltype :表达式类型推动

auto

1. 类型推导

auto类型推导:auto定义的变量,可以根据初始化的值,在编译时推导出变量名的类型,可以通过=右边的类型推导出变量的类型。

auto a = 10;	//10是int型,可以自动推导出a是int
int i = 10;
auto b = i;	//b是int型
auto d = 2.0;	//d是double型
auto pi = new auto(1);	//pi被推导为 int *
const auto *xp = &a,u=6;	//xp是const int*类型,u是const int型
auto d = 0, f = 1.0; // error,0和1.0类型不同,对于编译器有二义性,没法推导
auto int b;		//error c11中auto不再表示存储类型指示符
auto s;			//error 没有初始化值 auto无法推导出s的类型

​ 由此可以看出,auto并不能代表一个实际的类型声明(s),知识一个类型声明的占位符。使用auto声明变量必须要有初始化值,以让编译器推断出她的实际类型,并在编译时将auto占位符替换为真正的数据类型。

2.auto的推导规则

int x = 0;
auto *ip = &x;	//ip->int*,auto->int
auto xp = &x;	//xp->int*,auto->int*

auto &c = x;	//c->int&,auto->int
auto d = x;		//d->int,auto->int

const auto e = x;//e->const int
auto f = e;		//f->int
const auto &g = x;//g->const int &
auto &h = g;	//h->const int &

从上面的实力中可以看到auto的一些使用方法。他可以同指针、引用结合起来使用,还可以带上 cv 限定符(const等限定符)。

我们可以通过上面的实例得到以下两条规则:

  • 当不声明为指针或引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后类型一致。
  • 当声明为引用或指针时,auto的推导结果将保持初始化表达式的cv属性。

3.auto作为函数的形参类型

void func(auto x)
{
	cout<<sizeof(x)<<endl;
	cout<<typeid(x).name()<<endl;//typeid:获取类型名
}
int main
{
	int a = 10;
    int ar[] = {1,2,3,4};
    fun(a);
    fun(ar);
}

void func(auto &x)
{
	cout<<sizeof(x)<<endl;
	cout<<typeid(x).name()<<endl;//typeid:获取类型名
}
int main
{
	int a = 10;
    int ar[] = {1,2,3,4};
    fun(a);
    fun(ar);
}

4. auto的限制

struct foo
{
	suto value = 0;		//error auto不能用于非静态成员变量
	static const int num =10;// num->static const int
}
int main
{
	int ar[10]={0};
	auto br = ar;		//br->int*
	auto cr[10]=ar;		//error auto无法定义数组
	auto dr[5]={1,2,3,4};	//error auto无法定义数组
}

总结auto的限制:

  • auto的使用必须马上初始化,否则无法推导出类型
  • auto在一行定义多个变量时,各个变量的推导不能产生二义性,否则编译失败
  • 在类中auto不能用作非静态成员变量
  • auto不能定义数组,可以定义指针
  • auto无法推导出模板参数

5. auto可以推导函数返回类型

template<class T>
T my_max(T a,T b)
{
	return a>b?a:b;
}
int main
{
	auto x=my_max(12,13);
	auto y=my_max('a','b');
	return 0;
}

decltype

​ auto用于通过一个表达式在编译时确定带定义的变量类型,auto所修饰的变量必须被初始化,编译器需要通过初始化来确定auto所代表的类型,即必须要定义变量。若希望谷得到类型而不需要(或不能)定义变量的时候,C++11新增了decltype关键字,用来编译时推导出一个表达式的类型。

语法格式:decltype(exp)//exp表示一个表达式

decltype的推导过程是在便是期完成的,并且不会真正极端表达式的值。

int mian
{
	int x=10;
	decltype(x) y=1;	//y->int
	const int &i=x;
	decltype(i) j=y;	//j->const int &
	cosnt decltype(x) *p=&x;	//p->const int *
	decltype(x) *ip=&x;	//ip->int *
	decltype(ip) *pp=&ip//pp->int
}

函数表达式

int add(int a,int b)
{
	return a+b;
}
int main
{
	int x=10,y=20;
	decltype(my_add(0,0)) z;
	z=add(x,y);
	return 0;
}

auto和decltpe的配合使用

auto和decltype一般配合使用在推导函数返回值的类型上

template<typename T, typename U>
return_value add(T t, U u) { // t和v类型不确定,无法推导出return_value类型
    return t + u;
}

上面代码由于t和u类型不确定,那如何推导出返回值类型呢,我们可能会想到这种

template<typename T, typename U>
decltype(t + u) add(T t, U u) { // t和u尚未定义
    return t + u;
}

这段代码在C++11上是编译不过的,因为在decltype(t +u)推导时,t和u尚未定义,就会编译出错,所以有了下面的叫做返回类型后置的配合使用方法:

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

这段代码在C++11上是编译不过的,因为在decltype(t +u)推导时,t和u尚未定义,就会编译出错,所以有了下面的叫做返回类型后置的配合使用方法:

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

返回值后置类型语法就是为了解决函数返回制类型依赖于参数但却难以确定返回值类型的问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值