不想把 std::vector<int>::iterator 写全时,可以写 auto it = v.begin(),由编译器根据右边的表达式推出类型。这发生在编译期,不是 Python 那种运行期才定类型。decltype(表达式) 则直接问表达式的类型,常用于模板返回值。本节先跑 auto,再说明引用、const 与 decltype 的差别,并联系范围 for、Lambda。
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 1auto 会丢掉顶层 const 和引用。需要只读且不拷贝时,写成 const auto&;需要改元素时写成 auto&。
范围 for 里怎么写
字符串比 int 大,范围 for 里不要写裸 auto w(那会拷贝每一个 string):
#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:表示可能缺失的值与类型安全的联合体。