#include <iostream>
#include <type_traits> // 存在is_rvalue_reference、is_lvalue_reference、is_reference模板
using namespace std;
/*
左值:可以取地址的、有名字的就是左值;
右值:不可以取地址的、没有名字的是右值;右值是由两个概念构成的,一个是纯右值,另一个则是将亡值。
左值引用:对左值的引用,是具名变量值的别名,声明时必须初始化,不能对左值引用重定义。常量左值引用const T&,既可以绑定左值又可以绑定右值。
右值引用:对右值的引用,是不具名(匿名)变量的别名,声明时必须初始化,不能对右值引用重定义。已命名的右值引用,编译器会认为是个左值。
*/
// 移动语义
// std::move(lvalue) 的作用就是把一个左值转换为右值,当然传入一个右值,输出还是右值
// 值得注意的是: 使用move意味着,把一个左值转换为右值,原先的值不应该继续再使用(承诺即将废弃)
// 完美转发
// std::forward()完美转发实现了参数在传递过程中保持其值属性的功能,即若是左值,则传递之后仍然是左值,若是右值,则传递之后仍然是右值。
// 引用折叠
// 右值引用的右值引用,即X&& &&折叠为X&&
// 其他情况均折叠成左值引用,如X& &、X& &&、X&& &都折叠成X&
// 参数模板推断
// template<typename T>
// void f(T&&);
// 根据引用折叠原则,当将一个左值传递给一个参数是右值引用的函数,且此右值引用指向模板类型参数(T&&)时,编译器推断模板参数类型为实参的左值引用
// 当将一个右值引用传递给一个参数是右值引用的函数,且此右值引用指向模板类型参数(T&&)时,编译器推断模板参数类型为实参的右值引用
// auto
// 可以通过变量赋值,推导出变量的类型
// auto会忽略引用,如int i = 0 ,&r = i; auto a = r; //这里的a类型为int,并非int&
// auto会忽略顶层的const,如int i = 0; const int ci = i, &cr = ci; auto a = ci; // a 为一个int, 顶层const被忽略
// decltype
// 可以提取变量的类型,并通过这个类型区定义新的变量,并可以不去初始化变量,如 int a =0; decltype(a) b; // b是int型,而且可以不初始化
// decltype可以反会变量的顶层const和引用类型
int main()
{
// type_traits头文件中的模板可以判断引用类型
cout << is_reference<int>::value << endl; // 0
cout << is_rvalue_reference<string &&>::value << endl; // 1
cout << is_lvalue_reference<string &> ::value << endl; // 1
cout << is_rvalue_reference<const string &&>::value << endl; // 1
cout << is_lvalue_reference<const string &> ::value << endl; // 1
// 打印变量类型名称
int a = 41; // a是一个左值
class MyClass{};
MyClass myclass;
cout << "a:" << typeid(a).name() << endl; // typeid获取变量的类型信息,其中name是类型的名称
cout << "myclass:" << typeid(myclass).name() << endl; // 自定义类型名称包含.?AVMyClass@main@
// auto
cout << "auto:" << endl;
{
int &b = a; // b是a的引用
auto a1 = a; // a1是int
auto b1 = b; // b1是int
const int c = a, &d = c; // c是 const int, d是 const int&
cout << "a1:" << typeid(a1).name() << endl; // 输出a1是int
cout << "b:" << typeid(b).name() << endl; // 输出b是int
cout << "b1:" << typeid(b1).name() << endl; // 输出b1是int
cout << "c:" << typeid(c).name() << endl; // 输出c是int
}
// decltype
cout << "decltype:" << endl;
{
int &b = a; // b是a的引用
const int &c = a; // c是 const int&
int&& d = 1; // d是右值引用
cout << "a is_lvalue_reference:" << is_lvalue_reference<decltype(a)>::value << endl;// 0
cout << "b is_lvalue_reference:" << is_lvalue_reference<decltype(b)>::value << endl;// 1
cout << "c is_lvalue_reference:" << is_lvalue_reference<decltype(c)>::value << endl;// 1
cout << "d is_lvalue_reference:" << is_rvalue_reference<decltype(d)>::value << endl;// 1
}
return 0;
}
10-28
1175

03-17
881

04-24
1685

03-19
500

05-09