auto很好,即使可能有些缺点,也是瑕不掩瑜。
对于auto而言,其在于type deduce,那么第一点,它不会允许没有初始化值的声明,如:
int x; auto y; // error
这是很好的,有些开发者总是会直接用一些没有初始化的变量,然后后面运行结果不对。而运行的错误找起来总是比编译的难许多。
auto可以节省很多字,尤其是容器的iterator,这也是经常举的例子
vector<int> v; vector<int>::iterator iter = v.begin(); // #1 auto I = v.begin(); // #2
你是喜欢 #1 还是 #2这样的写法呢?
auto配合lambda使用很好。对于lambda来说,其是一个callable object,每一个类型都是独一无二的,这个类型只有编译器知道,于是你可以:
auto closure = [](const int&, const int&) {}
当然,你也可以使用std::function来存储,然而这远远没有auto来的优雅。
与此同时,在C++14中,泛型lambda也允许了参数类型可以为auto类型,如
auto closure = [](auto x, auto y) { return x * y;}
auto配合decltype,可以解决一些以前可能需要很丑的解法
template<class T, class U> ? ? ? mul(T x, U y) { return x*y; }
由于x, y是在参数,返回的是 x * y的类型,于是,要得到x * y的类型怎么办?当然可以利用decltype来取,但是你需要取的是 x * y的,而x,y却在参数后面,于是那就转为万能的0,在转为指针,再取指针。
template<class T, class U> decltype(*(T*)(0) * *(U*)(0)) mul(T x, U y) { return x*y; }
那么用auto占位置即可:
template<class T, class U> auto mul(T x, U y) -> decltype(x * y) { return x*y; }
Thanks to C++14, auto在C++14可以作为函数返回类型了,于是你可以直接这样了
template<class T, class U> auto mul(T x, U y) { return x*y; }
说完这么多好处,那么来说说auto可能引起的问题。
其中第一条可能就是很多人所说的可能会降低代码的可读性。然而对于这一条,我持中立态度。若有IDE,我认为这不会是问题,但是若你认为使用强制的类型声明可以让代码更可读,也可以继续使用,C++的哲学也是相信程序员,不会束缚你做什么任何事情。
然后第二条就是auto可能得不到你预想的类型,如vector<bool>[]的返回类型。
#include <iostream> #include <vector> #include <typeinfo> using namespace std; int main() { vector<bool> v; v.push_back(true); auto var = v[0]; cout << typeid(var).name() << endl; }
vector<bool>是一个奇葩的存在,它的[]返回的不是bool,是一个表示单独bool引用的proxy class,于是你得到是这个引用(而你平常使用bool没事,是因为完成了一个隐式转换),而你用auto的话,想要得到意想中的类型,需要使用static_cast<bool>,再给auto。而这也不是特例,其适用于含有proxy class的class。
3. auto配合decltype,有时候会让人有意想不到的结果。让我引用标准的一个例子
int i; int&& f(); auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)