auto 关键字是从c++11标准引入的,实际用起来还是非常爽的!
优点:
缺点:
- 当发生非预期的隐式转换时,可能会出现无法预知的错误
分析:
众所周知,用迭代器去访问容器打起来挺麻烦的,总是要写一长段:
vector<int> vct;
for(vector<int>::iterator it = vct.begin(); it != vct.end(); it++){...}
而使用auto关键字就能少打很多字:
vector<int> vct;
for(auto it = vct.begin(); it != vct.end(); it++){...}
又或者当我们使用类型转换时,使用显示强转强制 auto 推导出想要的类型,更能表达出代码类型转换的用意:(《Effective Modern C++》中的例子)
double calc();
float output = calc();
float output = (float)calc();
上述这种写法难以表明“我故意降低了函数的返回值精度”,但是这么却可以做到:
auto output = static_cast<float>(calc());
关于缺点,假设有一个函数接受一个 Widget 并返回 一个 std::vector<bool> ,其中每一个 bool 元素都代表着 Widget 是否提供一种特定功能:
vector<bool> features(const Widget& w);
Widget w;
bool highPriority = features(w)[5];
processWidget(w, highPriority);
若是对 highPriority 用 auto 来推导其类型时,代码依旧可以编译,但是行为则变得不可预期了:
auto highPriority = features(w)[5];
processWidget(w, highPriority);
为何会出现未定义行为?难道这里的 highPriority 不是 bool 类型吗?答案确实如此,从概念上来说,std::vector<bool> 中的元素应该就是 bool 型的,但 std::vector<bool> 的 operator[ ] 的返回值不是容器中的元素引用(其他类型都会返回对应元素的引用,但bool是个例外!),它返回的是 std::vector<bool>::reference 型的对象,至于为什么这里不做解释。 当用 bool highPriority 去接收 std::vector 的返回值时,底层会做一个隐式转换,从 std::vector::reference 到 bool 。 而使用 auto ,则会自动推导成 std::vector::reference ,这种非预期内的隐式转换就是导致出现未定义行为的罪魁祸首!!!
最后附上《Effective Modern C++》中的要点:
- “隐形”的代理型别可以导致 auto 根据初始化表达式推导出“错误的”型别。
- 带显示型别的初始化物习惯用法强制 auto 推导出你想要的型别。
|