auto、decltype
C++11引入了两个关键字用于类型推导:auto和decltype。两个关键字的用法有所不同,可以在不同场景中应用,也可以结合使用在某些场景中。
auto和decltype是在编译时推导确认变量类型,所以也不会影响性能。
auto类型推导
auto推导的变量必须被初始化。因为编译器需要通过初始化来确定auto所代表的类型、即需要定义变量。
auto x = 5; //x被推导为int类型 auto s; //错误,auto无法推导没有被初始化的s的类型。 auto s = x; //s被推导为和x一样的int类型
auto应用场景
auto在一些STL容器中有比较好的用武之地。特别是迭代器的遍历,例如:
#include <map> int main() { std::map<double, double> mp; ; for(std::map<double, double>::iterator it = mp.begin(); it != mp.end(); ++it) { //处理it内容 } return 0; }
应用auto做类型推导
#include <map> int main() { std::map<double, double> mp; ; for(auto it = mp.begin(); it != mp.end(); ++it) { //处理it内容 } return 0; }
可以看出使用auto后,代码简洁了许多。
decltype关键字
刚刚提到auto在推导变量类型时,所修饰的变量必须初始化。那不需要初始化的场景就需要使用到decltype关键字来做类型推导。
例如:
int x = 0; decltype(x) y; //y 被推导为int类型 decltype (x + y) z = 0;//变量 z 被推导为 int 类型,通过使用 decltype 推导 x + y 的结果类型,并将其初始化为 0。
decltype应用场景
decltype通常应用在泛型编程中。例如常见模板类:
template <class ContainerT> class Foo { public: void func(ContainerT& container) { it_ = container.begin(); } private: decltype(ContainerT().begin()) it_; };
auto和decltype结合使用
template <typename T, typename U> decltype(t + u) add(T t, U u) //错误, t,u在推导的时候还没有被定义 { return t + u; }
这段代码编译不过,因为t,u在参数列表中,C++的返回值是前置语法,这里先推导返回值类型是找不到u,t的定义。
可以修改为返回类型后置语法:
template <typename T, typename U> auto add(T t, U u) -> decltype(t + u)//可以编译通过 { return t + u; }
这也是auto、decltype最常用的组合用法。
进一步举例,decltype推导函数返回值也可以:
int& foo(int& i); float foo(float& f);//这里是foo重载 template <typename T> auto func(T& val) -> decltype(foo(val)) { return foo(val); }