先记一下函数指针与函数引用
函数指针void(*f) (int ,int) = f01;,函数引用void(&f) (int ,int) = f01;
函数指针可以指向别的函数(签名一致即可),函数引用不可以更改指向(也就是不能改变被引对象)。

模板类型推导

  • 在模板类型推导时,实参的引用性会被忽略
  • 对万能引用推导时,左值实参会有特殊处理
  • 值传递时,实参的常量性会被忽略(注意const char const被忽略的是右边的const,其类型为cosnt char

auto类型推导

在大多数情况下,auto推导与模板型别推导一样,但是在使用大括号初始化值时,会得到一个std::initializer_list<T> 的类型。
在函数返回值和lambda中使用auto不会推导出std::initializer_list<T>

诡异的decltype(auto)

  1. int i = 1;
  2. const int& ri = i;
  3. auto x1 = ri; // int
  4. decltype(auto) x2 = ri; // const int&

看编译器推导出了啥

可以依赖IDE,也可以用typeid(T).name(),还可以用boost库的Boost.TypeIndex,其中IDE(vs做的比较好,clion对模板函数的推导就没有显示,用auto推导可以看到)和boost比较准。

多用auto,可以避免类型不匹配等问题,还可以少写代码

存在一些隐形代理类,影响auto的发挥,要写硬类型

std::vector 是vector的一个特化,内部使用了比特压缩表示法,它的operator[]会返回std::vector::reference,然后有一个向bool的隐式类型转化,用auto接受到的是std::vector::reference,它会记录一个地址以及偏置来表示哪一个比特位,若此时原std::vector被析构,对std::vector::reference的使用会带来一个未定义的行为。

不放弃auto

遇到隐形代理类或是一些其他需求时(如double转int),继续沿用auto,并用static_cast进行类型转化

  1. vector<bool> v;
  2. auto t = static_cast<bool>(v[5]);
  3. double d = 0.5;
  4. auto x = static_cast<int>(d * 100);

这样也更有可读性