虽然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类型。之所以会会出现这种结果是因为STL对std::vector<bool>的operator[]函数做过特殊,用一种压缩的方式表示其持有的bool元素,即,每个bool元素用一个比特位来表示。正常来说,std::vector<T>的operator[]函数返回的应该为T&,但是C++却禁止比特位的引用,所以std::vector<bool>的operator[]函数返回的是std::vector<bool>::reference类型,且std::vector<bool>::reference类型做了一个向bool类型的隐式转换,正是因为这种隐式转换的存在,我们才可以使用使用bool类型来接收std::vector<bool>::reference。

上面std::vector<bool>的情况实际是使用了代理类的场景std::vector<bool>::reference是bool的代理,可能你会问,我们怎么知道某些库函数是否使用了代理呢?方法很简单,看源码。源码是可以看出来,但是如果每次使用一个库函数都要去看一下源码,无疑是降低了我们的开发效率,所以这里就介绍了一种一劳永逸的方法:使用带显示型别的初始化,说直白点就是在赋值前,进行显示强制类型转换。不仅对于std::vector<bool>的operator[]函数,当用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());