条款5:优先选用auto,而非显式型别声明
简化声明
auto defefLess = [](const auto& p1, const auto& p2) {return *p1 < *p2; };
引入:
std::function
这个是函数指针的一种推广,可以指涉任何可调用对象。若要创建一个std::function对象就必须指定欲指涉的函数的型别。
例如:
bool(const std::unique_ptr<widget>&, const std::unique_ptr<widget>&)//对应std::function<bool(const std::unique_ptr<widget>&, const std::unique_ptr<widget>&)> func;//因为lambda表示式产生可调用对象,std::function对象中就可以存储闭包。 所以在c++11中,不用
//auto也可以声明上面的derefUPLess
std::function<bool(const std::unique_ptr<widget>&, const std::unique_ptr<widget>&)>
注意:
std::function对象一般都会比使用auto声明的变量使用更多内存。通过std::function来调用闭包几乎必然会比通过使用auto声明的变量来调用同一闭包来的慢。
除了避免未初始化变量和啰嗦的变量声明,并且可以直接持有闭包外,还可以避免一类称为“型别捷径”的问题。
例如:
std::unordered_map<std::string, int> m;for(const std::pair<std::string, int>& p : m)
{//...
}
因为std::unordered_map的键值部分是const,所以编译器会试图将std::pair<const std::string, int>对象转换为std::pair<std::string, int> 对象。
结果会对m中的每个对象做一次复制操作,形成一个p想要绑定的型别的临时对象,然后将p这个引用绑定到该临时对象上,迭代结束后会析构该临时对象,使用auto可以避免这种隐晦的问题。
条款6:当auto推导的型别不符合要求时,使用带显式型别的初始化物习惯用法
例如:
Widget w;bool highPriority = features(w)[5];processWidget(w, highPriority)/////////////////////////////////auto highPriority = features(w)[5];processWidget(w, highPriority);
因为std::vector<bool>::operator[]特化为std::vector<bool>::reference对象,所以会出问题(highPriority含有一个垂悬指针)。
通常的,避免写出 auto somevar = "隐形"代理型别表达式。
但是可以这样:
auto highPriority = static_cast<bool>(features(w)[5]);
所以
1:一些不明显的代理类有可能使得你的auto推断与设想中的不一致。
2:显式初始化转化可以使得auto推导出想要的型别。