说明
auto
auto在早期C++中的标识临时变量,由于使用极少且多余,在C++11中已被用作类型推导使用。 auto自动类型推断,用于从初始化表达式中推断出变量的数据类型,可以简化我们的编程工作。
使用
map<int, map<int,int> > map;
map<int, map<int,int>>::const_iterator itr1 = map.begin();
const auto itr2 = map.begin();
auto i = 1;
注意项
auto声明的变量必须初始化,这样编译期才能从初始化代码中推导出返回类型。 使用auto就不能在定义数据类型。 auto是一个推导关键词,并不是一个数据类型,因此不能用于类型转换或其他一些操作,如sizeof和typeid。 推导不同数据类型必须独立开了,不能写在一起,例如:
auto x1 = 5, x2 = 5.0, x3='r'; //错误使用
auto不能自动推导成CV-qualifiers(constant & volatile qualifiers),除非被声明为引用类型,如下:
const int i = 100;
auto j = i; //错误用法
auto &k = i; //正确用法
auto会退化成指向数组的指针,除非被声明为引用
int a[9];
auto j = a;
cout<<typeid(j).name()<<endl; // This will print int*
auto& k = a;
cout<<typeid(k).name()<<endl; // This will print int [9]
如果初始化表达式是引用,则去除引用语义
int a = 10;
int &b = a;
auto c = b;//c的类型为int而非int&(去除引用)
auto &d = b;//d的类型才为int&
decltype
auto除了自动推导出数据类型还必须使用表达式的值去初始化变量,有时候只需要获取表达式的返回类型,这时该使用decltype,在推导过程中,编译器只是分析表达式并获取它的类型,却不进行实际的计算表达式的值。 例子:
decltype(f()) sum;//sum的类型就是函数f的返回值类型。
注意项
decltype在处理const和引用的方式与auto有些许不同,如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括const和引用在内),如下:
const int ci = 42, &cj = ci;
decltype(ci) x = 0; // x 类型为const int
auto z = ci; // z 类型为int
decltype(cj) y = x; // y 类型为const int&
auto h = cj; // h 类型为int
declval
decltype 可以推导出表达式的数据类型,但是某些情况下,例如:类的成员函数,如果没有对象,成员函数无法调用,自然无法推导,而declval就是解决这种情况下的自动推导,在推导过程中,declval不需要构造实例。
使用
template<class T>
typename std::add_rvalue_reference<T>::type declval() noexcept;
#include <utility>
#include <iostream>
class Default {
int foo() const { return 1; }
};
class NonDefault{
NonDefault(const NonDefault&) { }
int foo() const { return 1; }
};
int main()
{
decltype(Default().foo()) n1 = 1; // type of n1 is int
decltype(NonDefault().foo()) n2 = n1; // 错误: NonDefault没有默认的构造函数
decltype(std::declval<NonDefault>().foo()) n2 = n1; // 正确使用
}
auto和decltype配合使用
template<class T, class U>
??? mul(T x, U y){
return x*y;
}
这种情况下问号处最好能使用自动推导,正常使用应该为:
decltype(x*y)
但是由于x和y都是后面传入的,因此可以使用以下替代
decltype(*(T*)(0) * *(U*)(0))
template<class T, class U>
decltype(*(T*)(0) * *(U*)(0)) mul(T x, U y){
return x*y;
}
为了避免使用这种难看的写法,C++使用auto来占位,如下写法就可以:
template<class T, class U>
auto mul(T x, U y) -> decltype(x*y) {
return x*y;
}
template<class T, class U>
auto mul(T x, U y){
return x*y;
}
auto与decltype的区别
auto 关注的是表达式返回值的数据类型,而decltype关注的是表达式本身的数据类型。 auto忽略顶层const,decltype保留顶层const。 对引用操作,auto推断出原有类型,decltype推断出引用。 对解引用操作,auto推断出原有类型,decltype推断出引用。 auto推断时会实际执行,decltype不会执行,只做分析。
在使用中过程中和const、引用和指针结合时需要特别注意两者的区别。