auto关键字原理
在定义变量的时候必须申明类型,c++是强语言类型,在编译阶段需要知道类型,这样的好处是程序效率更高,而动态语言不需要类型申明的需要自推导变量类型。使用了auto是不是c++效率会变慢?完全不是,因为在编译阶段编译器已经帮程序员推导好了变量的类型。前提条件是编译器可以根据当前的程序的状态推导出变量类型。只是编译器更加智能,我猜想编译时间岂不更长了。
auto关键字使用场景
场景一,申明普通变量
[cpp] view plain copy
auto num = 10;
场景二,函数返回值,如果没有auto,总是要巧那么长的返回值,有了auto关键字后,是不是心里感觉很爽。
view plain copy
vector<string> str_vec;
vector<string>::iterator it_old = str_vec.begin();
auto it_new = str_vec.begin();
场景三,申明函数返回值
auto add(int a, int b)->int {
return a + b;
}
decltype用法
推导出表达式类型
int i = 4;
decltype(i) a; //推导结果为int。a的类型为int。
与using/typedef合用,用于定义类型。
using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型
using ptrdiff_t = decltype((int*)0 - (int*)0);
using nullptr_t = decltype(nullptr);
vector<int >vec;
typedef decltype(vec.begin()) vectype;
for (vectype i = vec.begin; i != vec.end(); i++)
{
//...
}
这样和auto一样,也提高了代码的可读性。
重用匿名类型
在C++中,我们有时候会遇上一些匿名类型,如:
struct
{
int d ;
doubel b;
}anon_s;
而借助decltype,我们可以重新使用这个匿名的结构体:
decltype(anon_s) as ;//定义了一个上面匿名的结构体
泛型编程中结合auto,用于追踪函数的返回值类型
这也是decltype最大的用途了。
template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty)
{
return x*y;
}
decltype推导四规则
如果e是一个没有带括号的标记符表达式或者类成员访问表达式,那么的decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译错误。
否则 ,假设e的类型是T,如果e是一个将亡值,那么decltype(e)为T&&
否则,假设e的类型是T,如果e是一个左值,那么decltype(e)为T&。
否则,假设e的类型是T,则decltype(e)为T。
标记符指的是除去关键字、字面量等编译器需要使用的标记之外的程序员自己定义的标记,而单个标记符对应的表达式即为标记符表达式。例如:
int arr[4]
则arr为一个标记符表达式,而arr[3]+0不是。
我们来看下面这段代码:
int i=10;
decltype(i) a; //a推导为int
decltype((i))b=i;//b推导为int&,必须为其初始化,否则编译错误
仅仅为i加上了(),就导致类型推导结果的差异。这是因为,i是一个标记符表达式,根据推导规则1,类型被推导为int。而(i)为一个左值表达式,所以类型被推导为int&。