每周技巧 #232:变量声明中何时使用 `auto`
本节阅读量:本文翻译自 Abseil 官网的 Tip of the Week #232: When to Use auto for Variable Declarations。
原文最初作为 TotW #232 发布于 2024 年 6 月 20 日。
作者:Kenji Inoue 和 Google 工程师 Michael Diamond
更新于 2024 年 9 月 30 日。
快捷链接:abseil.io/tips/232
风格指南在类型推导(包括 auto)一节中说:
只有在能让不熟悉项目的读者觉得代码更清晰,或者让代码更安全时,才使用类型推导。不要仅仅为了避免书写显式类型的不便而使用它。
讽刺的是,过度使用 auto 往往会让代码变得更不清晰。不过随着时间推移,一些模式已经浮现出来,在这些模式中使用 auto 可以提升代码清晰性和安全性,例如:
- 正确指定类型可能很困难,且指定错误类型会导致性能或正确性问题的情况,例如对 map 做基于范围的
for循环。 - 类型信息确实冗余,写出完整类型会分散注意力的情况,例如常用模板化工厂函数和某些迭代器用法。
- 泛型代码中,只要语法正确,类型本身并不重要的情况。
下面会逐一讨论这些情况,重点澄清哪些情况下 auto 会让代码更安全或更清晰。
对 map 的基于范围的 for 循环
下面代码有个问题:map 中每个元素都会被无意拷贝:
|
|
意外拷贝发生的原因是,关联容器的 value_type 是 std::pair<const Key, Value>,而如果底层类型可以隐式转换,std::pair 允许 pair 对象之间发生隐式转换。这里 std::pair::first_type 是 std::string,而 map 条目的 std::pair::first_type 是 const std::string,两个 pair 不是同一类型,于是发生隐式转换,尽管 name_and_breed 声明为引用,pair 内容仍被拷贝。
使用 auto,可能再结合结构化绑定(技巧 #169),可以让代码更安全、性能更好:
|
|
有时元素类型无法从局部上下文明显看出。在这种情况下,可以这样做:
|
|
迭代器
迭代器类型名称冗长,并且当容器类型在附近可见时,往往提供冗余类型信息。
下面代码片段把迭代器赋给一个局部变量:
|
|
所有容器都会暴露 begin() 和 end() 函数,它们返回迭代器,而这些迭代器类型是 ContainerType::iterator 或 ContainerType::const_iterator。
当容器类型在附近可见时,写出这些类型只有一个小好处:区分 iterator 和 const_iterator。因为容器类型部分(例如 std::vector<std::string>)与容器本身相同。在这种情况下,我们可以使用 auto 移除冗余,而不隐藏有用信息:
|
|
当容器类型在局部不可见时,优先写出完整迭代器类型或元素类型:
|
|
|
|
std::make_unique 和其他广泛使用的工厂函数
在下面代码片段中,std::make_unique 和 proto2::MakeArenaSafeUnique 指定了要实例化的类型。
|
|
大家普遍知道 std::make_unique<T> 返回 std::unique_ptr<T>,proto2::MakeArenaSafeUnique<T> 返回 proto2::ArenaSafeUniquePtr<T>。特别是,结果类型中重要的部分 T 已经在右侧表达式中指定,而且这是广泛知识,不是项目特定知识。这里可以使用 auto 移除冗余,而不隐藏有用信息:
|
|
泛型代码
编写泛型代码时,例如模板或 GoogleTest matcher,有些情况下类型可能无法指定或非常难指定(例如通过模板元编程或 decltype 写出的类型)。这些情况下 auto 也可能合适。不过,这些情况应该很少见。
其他情况:避免使用 auto
当类型很长且对你来说似乎显而易见时,使用 auto 可能很诱人,但请记住,未来的代码读者可能不熟悉你的项目及其使用的类型。例如,考虑一个常见的嵌套 proto 访问模式。
|
|
auto 还可能隐藏 const 性、类型是否为指针、是否发生拷贝等基本语义(技巧 #44)。
|
|
|
|
建议总结
- 当手写更具体类型有较高正确性或性能风险时,使用
auto。 - 当有用的类型信息在局部可见时,使用
auto移除冗余,而不隐藏有用信息。 - 对于某些类型无法指定或很难指定的泛型代码,
auto可能合适;这些情况应该很少见。 - 其他情况下避免使用
auto:虽然它可能让你更容易写代码,或者避免换行,但它很可能让不熟悉你项目的人更难理解代码。
相关阅读
- https://google.github.io/styleguide/cppguide.html#auto 权威指导
- 技巧 #4:Automatic for the People
- 技巧 #44:Qualifying auto