1. 类型推导的意义及缺点
①理解编码器类型推导规则有利于高效的使用c++;
②从冗余的类型拼写中解放出来;
③缺点:滥用会导致代码可读性降低;
2. 主要的应用场景
①调用函数模板
②使用auto
③decltype表达式
3. 函数模板的类型推导规则
(1)推导规则
按对象传递 | 传对象名:会去除实参对象的const属性 |
传引用:去除引用和const属性 | |
传指针:保留指针特性、保留const特性 | |
按引用传递 | 传对象名:保留对象cv属性 |
传对象引用:丢弃引用属性,保留cv属性 | |
传对象指针:保留指针特性、保留cv属性 | |
按指针传递 | 传对象指针:保存cv属性,丢弃指针属性 |
按万能引用传递 |
传对象名:①传左值就推导为左值引用;②传右值就推导为右值引用 |
(2)引用折叠规则
①当有左值引用折叠时,推导成左值引用;
②只有当全部为右值引用时,才为右值引用;
(3) 完美转发
①定义:把函数模板将收到的参数及参数类型不变的传递给其他参数叫做转发;
②最优解:采用万能引用
③若转发接收的函数形参为右值,有两种办法可以实现:一是std::move(),能够实现左值转右值;二是std::forward()可以实现左右值互相转换;
4. auto类型推导规则
(1)auto的类型推导规则基本与函数模板的类型推导规则一致;
(2)c++20 前auto不能用于函数参数;
5. decltype 表达式
(1)用法就是,可以给decltype一个变量或者表达式,decltype则可以利用该变量或表达式结果的类型来声明变量;注意在这个过程中decltype并不计算表达式的值或者调用相对应函数;
(2)推导规则:指针推断指针,引用推断引用,表达式如果可以做左值,则返回左值引用;当利用函数取推导时,则根据的是返回值的类型去推导;
6. auto与decltype的区别
(1)auto忽略顶层const,decltype保留顶层const;
(2)引用操作,auto推断出原有类型,decltype推断出引用;
(3)解引用操作(对指针取值),auto推断出原有类型,decltype推断出引用;
(4)auto推断时会实际执行,decltype不会执行,只做分析;
7. 小结
(1)当一个函数是右值引用,但实参是左值,可利用std::move()将实参转为右值,再调用右值引用函数;
(2)还可以多写一个同功能左值引用函数,这样就不用std::move(),通过函数重载实现;
(3)当函数要左值引用,但实参为右值时,可用std::forward<类型>(右值)来实现从右值转换为左值;
(4)需要注意的是左值引用只可以绑定左值,其引用名还是左值;右值引用只可绑定右值,但其引用名还是右值;
8. decltype示例
#include <iostream>
using namespace std;
template<typename T>
void print(T &&num)
{
cout<<num<<endl;
}
int main(int argc, char **argv)
{
int num = 5;
print(5);
print(num);
decltype(++num)temp1 = num; //temp1是引用,这里必须要初始化
cout<<"temp1 = "<<temp1<<endl;
decltype(num++)temp4; //temp4是整型,可以不初始化,是随机值
cout<<"temp4 = "<<temp4<<endl;
int name[100];
cout<<"name = "<<name<<endl;
decltype(name)temp2; //temp2是一个指针,指向的位置与name不同
cout<<temp2<<endl;
int &lnum = num;
decltype(lnum)temp3 = num; //temp3是引用
return 0;
}