虽然auto用起来确实好处多多,到那时也并不是万能的,在有些场景下,我们就不得不使用带显示型别的初始化。例如如下代码:
std::vector<bool> features() {
std::vector<bool> temp;
for(int i = 0;i < 10; ++i) {
temp.push_back(true);
}
return temp;
}
auto result = features()[5]; //编译通过,但实际将导致未定义行为
bool result2 = features()[5]; //正确
上述代码很简单,一个函数返回一个vector对象,里面放了10个true,然后使用auto接收第6个(从0开始计算)值,我们理所当然的认为,此时result的值为bool类型,但是实际上并不是,std::vector<T>对于bool类型且仅仅对bool类型有特殊处理,其返回值为并不是bool,而是std::vector<bool>::reference类型,它是bool类型的代理类。之所以出现这种结果,是因为STL对std::vector<bool>的operator[]函数做过特殊,用一种压缩的方式表示其持有的bool元素,即每个bool元素用一个比特位来表示。
上述代码中,result2变量被显示声明为bool类型,所以features()[5]将被隐式转换为bool类型,此时并不会有任何问题,但对于使用auto声明的result变量来说,features()[5]的类型为std::vector<bool>::reference,此时result中含有空悬指针,使用它将会导致未定义的行为。
但需要说明的是,上面问题的触发原因并不是auto导致的,所以我们不必舍弃auto语法,相反对于一些存在代理类或者隐试转换表达式,我们应该使用带显示型别的初始化,说直白点就是,如果我们确定表达式返回值,我们可以在赋值前,进行显示强制类型转换。例如上面代码的auto语句,我们可以改成这样:
auto result = static_cast<bool>(features()[5]);
auto sum = static_cast<MyType>(m1 + m2 + m3);
auto index = static_cast<int>(d * c.size());
auto diff = static_cast<float>(1.2);
本文介绍了C++中auto自动推导并非万能。以std::vector<bool>为例,使用auto接收其operator[]返回值时,结果并非bool类型,而是代理类类型,使用可能导致未定义行为。但问题并非auto导致,对于存在代理类或隐式转换表达式,可使用带显示型别的初始化或强制类型转换。
1361

被折叠的 条评论
为什么被折叠?



