auto

 

Item 1:优先选用auto,而非显式类型声明

 

在C++11中,使用auto关键字可以将程序员从输入繁琐的类型中解放出来。
Example:

//简化前的代码
void loopover(std::vector<std::string> &vs)
{
    for (std::vector<std::string>::iterator i = vs.begin(); i < vs.end(); i++)
    {
        //code
    }
}

//简化后的代码
void loopover(std::vector<std::string> &vs)
{
    for (auto i = vs.begin(); i < vs.end(); i++)
    {
        //code
    }
}
上例中,auto能够自动推导出vs.begin()的类型,从而避免了冗长的类型说明,该用法是值得大力推荐的。

Item 2:当auto推导出的类型不符合要求时,使用带显式类型的初始化物习惯用法

一个普遍的规律是,“隐形”代理类和auto不能够和平共处,倘若直接连用会导致未定义行为。

Example:

std::vector<bool> features(const Widget& w);
Widget w;
...
bool highPriority = features(w)[5];//假设第5个bit表示Widget是否有高优先级
...
processWidget(w,highPriority);


上述代码没有什么问题,若将highPriority的显式的类型换作auto:

auto highPriority = features(w)[5];

所有代码仍可编译,但其行为变得不可预测。

这里std::vector::operator[]对其他形参类别而言都返回容器中元素的引用,单单bool是个例外,它返回的是std::vector<bool>::reference类别的对象,
属于“隐式”代理类型。auto与其直接连用会导致未定义行为。 因此要防止这样的代码: auto someVar
= "隐形"代理类别表达式 在这种情况下,不要放弃auto,而是选择进行一次强制类型转换。 如上例可改为: auto highPriority = static_cast<bool>(features(w)[5]); 这样既保证了正确性,又不必放弃auto所具有的好处。
 
所谓代理类,是为了模拟或增广其他类型的类。其用途广泛,比如vector<bool>::reference就是为了制造vector<bool>的operator[]返回了一个bit的引用假象。再比如,标准库中的智能指针也是代理类,它们是为了将资源管理嫁接到裸指针之上。
 
同样属于代理类阵营的,还有一些C++库中的类,它们采用了表达式模板的技术,这些库最开始是为了提高数值运算的效率。
举一个例子,提供一个 Matrix 类和 Matrix 对象 m1, m2, m3和m4 ,下面的表达式:
Matrix sum = m1 + m2 + m3 + m4;

如果Matrix对象的operator+返回的是结果的代理,而非结果本身,则上述表达式的计算会高效得多。(这样不必每步都进行计算,而是先存着,等到用到计算得时候再去计算)。所以,两个Matrix对象的operator+会返回一个代理类对象,比如Sum<Matrix,Matrix>,而不是一个Matrix对象。

posted @ 2020-09-19 17:28  心媛意码  阅读(558)  评论(0编辑  收藏  举报