1. 从 C++11 开始,可以通过初始化表达式自动推导对象类型
2. 自动推导类型并不意味着弱化类型,对象还是强类型
3. 自动推导的几种常见形式
● auto: 最常用的形式,但会产生类型退化
类型退化:int& —>int const int& —> int
//类型退化#include <iostream>#include <type_traits>int main(){int x = 3;int& ref = x;auto y = ref;std::cout << std::is_same_v<decltype(y),int> << std::endl;}

● const auto / constexpr auto: 推导出的是常量 / 常量表达式类型
程序会进行自动类型匹配,找到最符合的那个类型
#include <iostream>#include <type_traits>int main(){auto x = 3;const auto y = 3;constexpr auto z = 3;std::cout << std::is_same_v<decltype(x),int> << std::endl;std::cout << std::is_same_v<decltype(y),const int> << std::endl;std::cout << std::is_same_v<decltype(z),const int> << std::endl;}

#include <iostream>#include <type_traits>int main(){const int x = 3;const auto y = x; // const int --> intauto z = x;std::cout << std::is_same_v<decltype(y),const int> << std::endl;std::cout << std::is_same_v<decltype(z),int> << std::endl;}

● auto& : 推导出引用类型,避免类型退化
#include <iostream>#include <type_traits>int main(){const int x = 3;auto& y = x;std::cout << std::is_same_v<decltype(y),const int&> << std::endl;const int& a = 3;auto& z = a;std::cout << std::is_same_v<decltype(z),const int&> << std::endl;}

再来看一下auto 和 auto& 的比较(以数组为例)
#include <iostream>#include <type_traits>int main(){int x[3] = {1,2,3};auto x1 = x;std::cout << std::is_same_v<decltype(x1),int*> << std::endl;auto& x2 = x;std::cout << std::is_same_v<decltype(x2),int(&)[3]> << std::endl;}

● decltype(exp) :返回 exp 表达式的类型(左值加引用)
● decltype(val) :返回 val 的类型
decltype 和 auto 相比不会发生类型退化
#include <iostream>#include <type_traits>int main(){int x = 3;int& y = x;auto y1 = y;decltype(y) y2 = y;std::cout << std::is_same_v<decltype(y1),int> << std::endl;std::cout << std::is_same_v<decltype(y2),int&> << std::endl;}

注意前面的auto&同样可以避免类型退化,但多了“引用”的额外负担;这里的y1的类型并不是const int,而是const int&。
#include <iostream>#include <type_traits>int main(){int x = 3;const int y = x;auto& y1 = y;decltype(y) y2 = y;std::cout << std::is_same_v<decltype(y1),const int&> << std::endl;std::cout << std::is_same_v<decltype(y2),const int> << std::endl;}

左值加引用
#include <iostream>#include <type_traits>int main(){int x = 3;int* ptr = &x;// ptr --> int*// *ptr --> int// 作为左值加引用 decltype(*ptr) --> int&std::cout << std::is_same_v<decltype(*ptr),int&> << std::endl;}

矛盾的地方:这里的x 和 ptr 都是左值,但decltype(x)并不是int&类型,原因在于x是一个变量名称,而ptr可以视为一个表达式
#include <iostream>#include <type_traits>int main(){int x = 3;int* ptr = &x;std::cout << std::is_same_v<decltype(*ptr),int&> << std::endl;std::cout << std::is_same_v<decltype(x),int> << std::endl;}

进一步验证:
#include <iostream>#include <type_traits>int main(){int x = 3;int* ptr = &x;std::cout << std::is_same_v<decltype(3.5 + 15l),double> << std::endl;std::cout << std::is_same_v<decltype(*ptr),int&> << std::endl;std::cout << std::is_same_v<decltype(x),int> << std::endl;std::cout << std::is_same_v<decltype(ptr),int*> << std::endl; // ptr视为一个变量名称,尽管位于左值,但不加引用}

进一步扩展:
#include <iostream>#include <type_traits>int main(){int x = 3;int* ptr = &x;std::cout << std::is_same_v<decltype(3.5 + 15l),double> << std::endl;std::cout << std::is_same_v<decltype(*ptr),int&> << std::endl;std::cout << std::is_same_v<decltype(x),int> << std::endl;std::cout << std::is_same_v<decltype(ptr),int*> << std::endl;// 加()使之转化为一个表达式std::cout << std::is_same_v<decltype((x)),int&> << std::endl;}
● decltype(auto) :从 c++14 开始支持,简化 decltype 使用
#include <iostream>int main(){decltype (3.5 + 15l) x = (3.5 + 15l);--->decltype (auto) x = (3.5 + 15l);}
● concept auto :从 C++20 开始支持,表示一系列类型( std::integral auto x = 3; )
增加一些限制:
#include <iostream>#include <type_traits>int main(){std::integral auto x = 4; //限制在整数类型std::cout << std::is_same_v<decltype(x),int> << std::endl;}

