C++ auto关键字浅析

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类型的计算函数
double calc();

// 假设在某处float精度已经足够用时,显然可以将计算结果转成float来储存
float output = calc(); 
// 或者
float output = (float)calc();

上述这种写法难以表明“我故意降低了函数的返回值精度”,但是这么却可以做到:

auto output = static_cast<float>(calc());

关于缺点,假设有一个函数接受一个 Widget 并返回 一个 std::vector ,其中每一个 bool 元素都代表着 Widget 是否提供一种特定功能:

vector<bool> features(const Widget& w);
Widget w;
bool highPriority = features(w)[5]; // 第5个元素表示 w 的优先级
processWidget(w, highPriority); // 根据优先级处理 w

若是对 highPriority 用 auto 来推导其类型时,代码依旧可以编译,但是行为则变得不可预期了:

auto highPriority = features(w)[5];
processWidget(w, highPriority); // 未定义行为!

为何会出现未定义行为?难道这里的 highPriority 不是 bool 类型吗?答案确实如此,从概念上来说,std::vector 中的元素应该就是 bool 型的,但 std::vector 的 operator[ ] 的返回值不是容器中的元素引用(其他类型都会返回对应元素的引用,但bool是个例外!),它返回的是 std::vector::reference 型的对象,至于为什么这里不做解释。
当用 bool highPriority 去接收 std::vector 的返回值时,底层会做一个隐式转换,从 std::vector::reference 到 bool 。
而使用 auto ,则会自动推导成 std::vector::reference ,这种非预期内的隐式转换就是导致出现未定义行为的罪魁祸首!!!


最后附上《Effective Modern C++》中的要点:

  • “隐形”的代理型别可以导致 auto 根据初始化表达式推导出“错误的”型别。
  • 带显示型别的初始化物习惯用法强制 auto 推导出你想要的型别。

你可能感兴趣的:(C++,c++,开发语言)