C11的新特性-auto关键字,decltype关键字

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

一、auto关键字

C11中auto成为类型指示符(type-specifier)。

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

int main()
{
	auto a = 10;//a int
	auto ip = new auto(1);//1 是整型,将整型的地址给ip, ip int* 
	auto dp = new auto(12.23);//dp double*

	return 0;
}

1)auto 推导类型不能有二义性

int main()
{
	auto x = 5;//int
	const auto* ip = &x;//ip int *,auto是int
	//const auto* ap = &x, u;//error ,u没有初始值,不能推演,必须给出初始值才可以推演
	const auto* ap = &x, u=10;//ok,虽然前面已经推导出auto的类型为int,但后面u仍然必须写初始值
	const auto* ap = &x, u = 12.23;//error,由&x可以推出auto是int,但是u=12.23,那么auto就得是double,这样具有二义性
	return 0;
}

 2)auto 推导类型变量必须初始化

不初始化无法推导类型。


int main()
{
	auto s;//error,没有初始化,无法推导
	auto int y;//error,auto 在c11中是推导类型,不再表示存储类型指示符
	return 0;
}

 3)auto的推导规则

auto可以同指针、引用结合起来使用,还可以带上cv限定符(cv-qualifier(修饰词),const和volatile限定符的统称)

int main()
{
	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 int
	auto f = e;//f->int ,auto int

	const auto& g = x;//g->const int &,auto 
	auto& h = g;//h->const int &
	//h是g的别名,g是const int&,不能通过h改变g,
	//h += 10;//error,h是常量,无法赋值
	auto y = g;//y->int,y= g,相当于将数值g给变量y

	return 0;
}

ip和c的推导结果是很显然的,auto在编译时被替换为int,因此a和c分别被推导为int*和int&。

xp的推导结果说明,其实auto 不声明为指针,也可以推导出指针类型。

d 的推导结果说明当表达式是一个引用类型时,auto 会把引用类型抛弃,直接推导成原始类型int。

e的推导结果说明,const auto会在编译时被替换为const int。

f的推导结果说明,当表达式带有const(实际上volatile也会得到同样的结果)属性时,auto会把const属性抛弃掉,推导成non-const类型int。

g、h的推导说明,当auto和引用(换成指针在这里也将得到同样的结果)结合时,auto的推导将保留表达式的const属性。

通过上面的一系列示例,可以得到下面这两条规则:
1)当不声明为指针或引用时,auto 的推导结果和初始化表达式抛弃引用和cv限定符后类型一致。2)当声明为指针或引用时,auto的推导结果将保持初始化表达式的cv属性。

4)auto 作为函数的形参类型

对于auto作为函数形参类型,版本要求很高,要提高属性设置的版本

设置步骤:

 

 如此,auto才可以作为函数的参数类型

void func(auto x)
{
	cout << sizeof(x) << endl;
	cout << typeid(x).name() << endl;
}
#include<iostream>
#include<typeinfo>
using namespace std;

void func(auto x)
{
	cout << sizeof(x) << endl;
	cout << typeid(x).name() << endl;
}
int main()
{
	int a = 10;
	int ar[] = { 1,2,3,4,5,6,7,8 };
	func(a);
	func(ar);//此时ar作为数组首元素的地址
	return 0;
}

参数引用

#include<iostream>
#include<typeinfo>
using namespace std;

void func(auto &x)
{
	cout << sizeof(x) << endl;
	cout << typeid(x).name() << endl;
}
int main()
{
	int a = 10;
	int ar[] = { 1,2,3,4,5,6,7,8 };
	func(a);
	func(ar);//引用数组,数组有两个属性,大小和类型
	//数组体现两个属性的地方:sizeof(ar);指针int(*p)[8]=&ar;引用 int (&br)[8]=ar;
	return 0;
}

int main()
{
	int a = 10;
	int ar[] = { 1,2,3,4,5,6,7,8 };

	auto b = ar;//b->int *
	auto& c = ar;//c->int (&c)[8]
	cout << sizeof(b) << endl;//8
	cout << sizeof(c) << endl;//32
	return 0;
}

5)auto的限制

struct Foo
{
	auto value = 0;//error,auto不能用于非静态成员变量
	static const int num = 10;//ok,num->static const int,必须是const和整型才可以用auto推导
};
int main()
{
	auto ar[] = { 1,2,3,4 };//error;auto只能推导基本数据类型,无法定义数组
	return 0;
}

1、C11中auto成为类型指示符(type-specifier)。

2、auto不能用于函数参数。

3、auto不能用于非静态成员变量

4、 auto无法定义数组

5、实例化模板时不能使用auto作为模板参数。

6)auto可以推导函数的返回类型

#include<iostream>
using namespace std;

template<typename T>
const T& Max(const T& a, const T& b)//引用返回
{
	return a > b ? a : b;
}
int main()
{
	auto a = Max(12, 23);//auto 可以推导出函数的返回值类型,值返回,以值的形式接收
	auto& b = Max(23, 34);//b ->const int &,引用接收,常性引用返回,
    //对于模板函数来说,用auto 接收函数的返回值,不用判断返回值类型是什么,可以直接接收,比较方便
    auto x = Max(24,25);
    auto y = Max('a','b');
	return 0;
}

二、decltype

auto,用于通过一个表达式在编译时确定待定义的变量类型,auto所修饰的变量必须被初始化,编译器需要通过初始化来确定auto所代表的类型,即必须要定义变量。

仅希望得到类型,而不需要(或不能)定义变量的时候应该怎么办呢?

C++11新增了decltype关键字,用来在编译时推导出一个表达式的类型,

它的语法格式如下:
        decltype (exp)
其中,exp表示一个表达式(expression) 
从格式上来看,decltype很像sizeof——用来推导表达式类型大小的操作符。

类似于sizeof,decltype的推导过程是在编译期完成的,并且不会真正计算表达式的值。

int main()
{
	int a = 10;
	cout << sizeof(a + 10) << endl;//4
	cout << sizeof(a + 10.25) << endl;//8
	sizeof(++a);//sizeof计算类型的大小,只关心类型的大小,在编译期计算大小,不会真正计算表达式的值
	int x = sizeof(++a);//x = 4
	cout << a << endl;//10

	return 0;
}

 类型的推演都是发生在编译期。

auto与decltype 的区别:

int main()
{
	int x = 10;
	decltype(x)y = 1;//x是int,推演出y也是int
	decltype(x + y) z = 10;
	decltype(x + y + 10.23)a = 10;//10.23是double,所以整体是double


	return 0;
}

 

int main()
{
	int x = 10;
	const int& a = x;//a是const int&
	decltype(a)b = x;//推导出b也是const int &
	//auto和decltype有些不同
	auto z = a;//a是const int&,在此相当于将数值直接给z,z是int
	auto& zz = a;//auto与引用、指针结合时,会保留const属性,zz是const int &

	return 0;
}

 

int main()
{
	int a = 10;
	const int* ip = &a;

	auto p1 = ip;//推导出p是const int *

	decltype(ip)p2 = &a;//p2是const int *

	return 0;
}

 


int my_add(int a, int b)
{
	return a + b;
}
int main()
{
	auto x = my_add(12, 23);//使用auto就会调用后面函数计算表达式的值,若我们只想得到返回类型,就可以使用declpyte
	decltype(my_add(12, 23))z;//使用declpyte不会计算表达式的值,只是在编译期得到表达式的返回类型
	z = my_add(12, 23);//z ->int

	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值