条款6:当auto推导的类型不符合要求时,使用带显示类型的初始化物习惯手法

有时候,你想往东,auto类型推导的结果偏偏往西。考虑如下代码:

std::vector<bool> features(cosnt Widget& w);
Widget w;
bool highPriority = features(w)[5]; 
processWidget(w, hightPrioirty);

上述代码没有什么问题,如果我们吧highPriority从显示类型改为auto呢?

auto highPriority = featrues(w)[5];

所有代码仍然可编译,但是其行为则变得不再可以预测了

processWidget(w, hightPrioirty); //未定义行为

上述函数调用中,highPriority的类型不再是bool了。它返回的是std::vector<bool>::reference类型的对象。之所以要弄出个std::vector<bool>::reference,是因为std::vector<bool>做过特化,用了一种压缩形式表示其持有bool元素,每个bool元素用一个比特来表示。这种做法给std::vector<T>operator[]带来一个问题,因为按说std::vector<T>operator[]应该返回T&,然而C++中给你却禁止比特的引用。、

auto highPriority = featrues(w)[5];

features的调用会返回一个std::vector<bool>类型的临时对象temp,针对temp执行operator[],返回一个std::vector<bool>::reference类型对象,该对象含有一个指涉及到机器字的指针,该机器字在一个持有temp所管理的那样比特币的数据结构中,还要加上第5个比特所对应的机器字的偏移量。由于highPrioritystd::vector<bool>::reference对象的一个副本,所以highPriority也含有一个指涉到temp中的机器字的指针,加上还要在第5个比特所对应的机器字的偏移量。在表达式结束处,temp会被析构,因为它是一个临时对象。结果,highPriority会含有一个空悬指针,最终导致processWidget时出现未定义行为。

std::vector<bool>::reference是一个代理类的实例。所谓代理类,就是为了模拟或增广其他类型的类;所以我们要防止写出以下这样的代码

auto someVar = "隐形"代理类型表达式
auto highPriority = static_cast<bool>featrues(w)[5]; //是一种安全做法
上一篇:Java中各种引用(Reference)解析


下一篇:boost::hana模块将 reference_wrappers 保存到其元素的元组