6.19. auto
Tip
用 auto
绕过烦琐的类型名,只要可读性好就继续用,别用在局部变量之外的地方。
定义:
C++11 中,若变量被声明成auto
, 那它的类型就会被自动匹配成初始化表达式的类型。您可以用auto
来复制初始化或绑定引用。
- vector<string> v;
…
auto s1 = v[0]; // 创建一份 v[0] 的拷贝。
const auto& s2 = v[0]; // s2 是 v[0] 的一个引用。
优点:
C++ 类型名有时又长又臭,特别是涉及模板或命名空间的时候。就像:
- sparse_hash_map<string, int>::iterator iter = m.find(val);
返回类型好难读,代码目的也不够一目了然。重构其:
- auto iter = m.find(val);
好多了。没有auto
的话,我们不得不在同一个表达式里写同一个类型名两次,无谓的重复,就像:
- diagnostics::ErrorStatus* status = new diagnostics::ErrorStatus("xyz");
有了 auto, 可以更方便地用中间变量,显式编写它们的类型轻松点。
缺点:
类型够明显时,特别是初始化变量时,代码才会够一目了然。但以下就不一样了:
- auto i = x.Lookup(key);
看不出其类型是啥,x 的类型声明恐怕远在几百行之外了。程序员必须会区分auto
和const auto&
的不同之处,否则会复制错东西。auto 和 C++11 列表初始化的合体令人摸不着头脑:
- auto x(3); // 圆括号。
auto y{3}; // 大括号。
它们不是同一回事——x
是int
,y
则是std::initializer_list<int>
. 其它一般不可见的代理类型(acgtyrant 注:normally-invisible proxy types, 它涉及到 C++ 鲜为人知的坑:Why is vector<bool> not a STL container?)也有大同小异的陷阱。如果在接口里用auto
, 比如声明头文件里的一个常量,那么只要仅仅因为程序员一时修改其值而导致类型变化的话——API 要翻天覆地了。
结论:
auto
只能用在局部变量里用。别用在文件作用域变量,命名空间作用域变量和类数据成员里。永远别列表初始化auto
变量。auto
还可以和 C++11 特性「尾置返回类型(trailing return type)」一起用,不过后者只能用在 lambda 表达式里。