6.19. auto

Tip

auto 绕过烦琐的类型名,只要可读性好就继续用,别用在局部变量之外的地方。

定义:

C++11 中,若变量被声明成 auto, 那它的类型就会被自动匹配成初始化表达式的类型。您可以用 auto 来复制初始化或绑定引用。

  1. vector<string> v;

    auto s1 = v[0]; // 创建一份 v[0] 的拷贝。
    const auto& s2 = v[0]; // s2 是 v[0] 的一个引用。


优点:

C++ 类型名有时又长又臭,特别是涉及模板或命名空间的时候。就像:

  1. sparse_hash_map<string, int>::iterator iter = m.find(val);


返回类型好难读,代码目的也不够一目了然。重构其:

  1. auto iter = m.find(val);


好多了。没有 auto 的话,我们不得不在同一个表达式里写同一个类型名两次,无谓的重复,就像:

  1. diagnostics::ErrorStatus* status = new diagnostics::ErrorStatus("xyz");


有了 auto, 可以更方便地用中间变量,显式编写它们的类型轻松点。

缺点:

类型够明显时,特别是初始化变量时,代码才会够一目了然。但以下就不一样了:

  1. auto i = x.Lookup(key);


看不出其类型是啥,x 的类型声明恐怕远在几百行之外了。程序员必须会区分 autoconst auto& 的不同之处,否则会复制错东西。auto 和 C++11 列表初始化的合体令人摸不着头脑:

  1. auto x(3); // 圆括号。
    auto y{3}; // 大括号。


它们不是同一回事——xint, 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 表达式里。