EMCPP条款5:优先选用auto而非显式型别声明

YiQi 管理员

避免冗长的型别声明

lambda 表达式的返回类型可以用 auto

1
2
3
4
auto derefUPLess = [](const std::unique_ptr<int>& lhs,
const std::unique_ptr<int>& rhs) {
return *lhs < *rhs;
};

在C++14中,labmda 表达式的参数列表中的参数也可以用 auto

1
2
3
auto derefUPLess = [](auto& lhs, auto& rhs) {
return *lhs < *rhs;
};

std::function 是C++11标准库中的一个模板,它把函数指针的思想加以扩展,使得它可以表示任何可调用的东西,包括函数、函数对象、lambda表达式、成员函数、成员函数指针、函数指针等等。对上述函数使用 std::function 声明:

1
2
3
4
5
6
std::function<bool(const std::unique_ptr<int>&,
const std::unique_ptr<int>&)> derefUPLess =
[](const std::unique_ptr<int>& lhs,
const std::unique_ptr<int>& rhs) {
return *lhs < *rhs;
};
  • 从结果上看,std::function 对象一般都会比使用 auto 声明的变最使用更多内存。
  • 从可读性上看,std::function 对象的声明比使用 auto 声明的变量要长得多。
  • 从性能上看,std::function 对象的声明比使用 auto 声明的变量要慢得多。

避免“型别捷径”的问题

比如,在32位Windows上,unsignedstd::vector<int>::size_type 的尺寸是一样的,但在64位Windows上,unsigned 的尺寸是4字节,而 std::vector<int>::size_type 的尺寸是8字节。使用 auto 就不会有这样问题。

1
2
std::vector<int> v;
auto sz = v.size(); // sz的型别是std::vector<int>::size_type

避免错误的隐式转换

比如:

1
2
3
4
5
std::unordered_map<std::string, int> m;
...
for (const std::pair<std::string, int>& p : m) {
...;
}

std::unordered_map 的键值是 const,所以 std::pair 的键值应该也是 const,即 std::pair<const std::string, int>。编译器会努力将 std::pair<const std::string, int> 转换成 std::pair<std::string, int>,这一步是可以成功的,但多了一次复制操作,所以最好还是使用 auto,即:

1
2
3
for (const auto& p : m) {
...;
}

要点速记

  • auto 变量必须初始化,基本上对会导致兼容性和效率问题的型别不匹配现象免疫,还可以简化重构流程,通常也比显式指定型别要少打一些字。
  • auto 型别的变量都有着条款2和条款6中所描述的毛病。
此页目录
EMCPP条款5:优先选用auto而非显式型别声明