不想把 std::vector<int>::iterator 写全时,可以写 auto it = v.begin(),由编译器根据右边的表达式推出类型。这发生在编译期,不是 Python 那种运行期才定类型。decltype(表达式) 则直接问表达式的类型,常用于模板返回值。本节先跑 auto,再说明引用、const 与 decltype 的差别,并联系范围 for、Lambda。

auto

C++ auto运行
#include <iostream>
#include <vector>

int main() {
    auto x = 42;          // int
    auto y = 3.14;        // double(本例只用来展示推导)
    std::vector<int> v{1, 2, 3};
    auto it = v.begin();  // vector<int>::iterator
    std::cout << x << " " << y << " " << *it << "\n";
    return 0;
}

输出:

42 3.14 1

auto 会丢掉顶层 const 和引用。需要只读且不拷贝时,写成 const auto&;需要改元素时写成 auto&。

范围 for 里怎么写

字符串比 int 大,范围 for 里不要写裸 auto w(那会拷贝每一个 string):

C++ const auto&运行
#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> words{"a", "bb", "ccc"};
    for (const auto& w : words) {  // 只读引用,不拷贝 string
        std::cout << w.size() << " ";
    }
    std::cout << "\n";
    return 0;
}

输出:

1 2 3 

decltype

decltype(a) 对变量名给出声明时的类型,这里是 int。decltype((a)) 多了一层括号,按表达式算,左值得到 int&。和 auto 不同:auto 会丢掉引用。

int a = 0;
decltype(a) b = 1;     // int
decltype((a)) c = a;   // int&,c 是 a 的别名
auto z = a;            // int,拷贝

C++11 可把返回类型写在后面:auto add(T a, U b) -> decltype(a + b)。C++14 起直接 auto add(T a, U b) { return a + b; } 即可,由 return 推导。

常见陷阱

情形建议
范围 for 写 auto大对象用 const auto&
公开函数返回类型接口上写出具体类型,便于阅读
decltype((x))得到引用,不要绑到马上要销毁的临时量

C++14 的 decltype(auto) 按 decltype 规则保留引用,用于转发函数;入门会读即可。

本节说明了 auto 与 decltype 的规则与注意点。下一节介绍optional 与 variant:表示可能缺失的值与类型安全的联合体。