合理使用 auto 关键字
6.3.1 ID_abusedAuto
auto 关键字隐藏了类型名称,在使用时需注意不应降低可读性。
非局部对象不宜用 auto 声明,如接口的返回类型、参数、全局对象等。如果局部对象的类型对程序的行为有显著影响,也不宜用 auto 声明。
示例:
auto foo() {
....
}
auto bar() {
auto x = foo();
....
return x;
}
auto obj = bar(); // What the hell is ‘obj’??
如果想确定 obj 对象的类型,必须通读所有与之相关的代码,可读性很差。
将代码中所有可以替换成 auto 的标识符全部替换成 auto,其结果是不可想象的,与 Python 等语言不同,C++ 语言存在重载、模板等多种严格依赖于类型的特性,如果类型名称不明确,必然会造成阅读和维护等方面的障碍。
下面给出 auto 关键字的合理用法:
Type* a = static_cast<Type*>(ptr); // Repeated type name
unique_ptr<Type[]> b = make_unique<Type[]>(10); // Repeated type name
重复的类型名称使代码变得繁琐,这种情况使用 auto 是更好的方法:
auto* a = static_cast<Type*>(ptr); // OK
auto b = make_unique<Type[]>(10); // OK
又如:
vector<Type> v{ .... };
vector<Type>::iterator i = v.begin(); // Verbose
begin 函数返回迭代器是一种常识,且迭代器类型名称往往较长,这种情况应使用 auto:
auto i = v.begin(); // OK
又如:
struct SomeClass {
struct Sub {
....
};
Sub foo();
};
SomeClass::Sub SomeClass::foo() { // Repeated ‘SomeClass’
....
}
重复的类作用域声明十分繁琐,可用 auto 关键字配合后置返回类型改善:
auto SomeClass::foo() -> Sub { // OK
....
}
总之,使用 auto 关键字的目的应是提高可读性,而不是单纯地简化代码。