条款5 优先使用auto而非显式类型声明

  • auto变量从它们的初始化推导出其类型,所以**auto**变量必须初始化;从而避免了普通声明忘记初始化。

  • 使用std::function和使用auto不一样。

使用auto声明持有一个封装的变量和函数对象有同样的类型,也仅消耗和函数对象同样大小的内存;使用std::function持有一个可调用对象的变量,类型是std::function模板的一个实例,并且对任何类型只有一个固定的大小。这个大小可能不满足需求,所以**std::function**的构造函数会额外开辟堆空间。结果就是**std::function**可能比**auto**对象使用更多内存

此外,由于实现细节中,约束内嵌的使用和提供间接函数的调用,使用std::function对象会比auto要慢。


  1. std::unordered_map<std::string, int> m;
  2. ...
  3. for(const std::pair<std::string, int>& p:m){
  4. ...
  5. }

**std::unordered_map**中 key 部分是 const 类型的,所以 pair 的实际类型应该是 std::pair

而且此处不是循环体外的变量p声明,所以编译器会将 std::pair<const std::sting, int> 转换为std::pair<std::sting, int> 。这个过程通过复制 m 中的一个元素到一个临时对象,然后将这个临时对象和 p 绑定

条款6 当auto推导出非预期类型时应当使用显式的类型初始化

  • std::vectoroperator[]运算符不一定返回容器中的元素引用(它对所有类型都返回引用,就是除了**bool**)。

事实上,返回的是一个std::vector::reference对象(是一个在(std::vector内嵌的 class)。

image.png


不可见的代理类不可以和auto一同使用。

代理类:以模仿和增强一些类型的行为为目的而存在的类

使用显式的类型初始化即可:

  1. auto ep=static_cast<float>(calcEpsilon());

这样就可以迫使 auto 推导出你想要的类型。