条款5 优先使用auto而非显式类型声明
auto
变量从它们的初始化推导出其类型,所以**auto**
变量必须初始化;从而避免了普通声明忘记初始化。
- 使用
std::function
和使用auto
不一样。
使用auto
声明持有一个封装的变量和函数对象有同样的类型,也仅消耗和函数对象同样大小的内存;使用std::function
持有一个可调用对象的变量,类型是std::function
模板的一个实例,并且对任何类型只有一个固定的大小。这个大小可能不满足需求,所以**std::function**
的构造函数会额外开辟堆空间。结果就是**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**
中 key 部分是 const 类型的,所以 pair 的实际类型应该是 std::pair
而且此处不是循环体外的变量p声明,所以编译器会将 std::pair<const std::sting, int>
转换为std::pair<std::sting, int>
。这个过程通过复制 m 中的一个元素到一个临时对象,然后将这个临时对象和 p 绑定。
条款6 当auto推导出非预期类型时应当使用显式的类型初始化
- 对
std::vector
的operator[]
运算符不一定返回容器中的元素引用(它对所有类型都返回引用,就是除了**bool**
)。
事实上,返回的是一个std::vector::reference
对象(是一个在(std::vector
内嵌的 class)。
不可见的代理类不可以和auto
一同使用。
代理类:以模仿和增强一些类型的行为为目的而存在的类。
使用显式的类型初始化即可:
auto ep=static_cast<float>(calcEpsilon());
这样就可以迫使 auto
推导出你想要的类型。