第七章、传值还是传引用

背景

在模板中有传值和传引用两种方式,不过传引用又可以分为const和non-const两种方式,在一些源码中经常充斥着模板编程,如果对类型推导不熟悉,很多时候想当然的结果会有很大误差,下面具体来分析。

传值

在传值之前,我们首先熟悉以下字面常量的类型,比如“hello”的数据类型是const char[6], 这里的6是因为尾部有个结束符,所以长度为5+1。下面先说两个传值时候类型推导遵循的结论:

  • 传值会把类型的const和volatile,&这些修饰符都给干掉
  • 对于数组,会把num的信息给干掉,直接转为指针
  • 无视左右值
template<typename T>
printV(T par)
{}
// demo
printV("hello");// T 被推导为const char*
//这里要重点说以下,这个数组为啥被推导为指针?这个是C语言的规定,这里有个大坑,就是类型中抛弃了6的信息,后面还要为此专门想办法解决。那么为啥const没有被干掉呢?这里说来话长,其实这里的const是*p的,不是P的。
int a = 1;
int& b = a;
const int& c = a;
printV(a);// T被推导为int
printV(b);// T被推导为int
printV(c);// T被推导为int
int d[3] = {1,2,3};
printV(d);// T被推导为int*
const int e[3] = {1,2,3};
printV(e);// T被推导为const int*, 和const char* 是一个德性;
int num = 3;
printV(std::move(num));// T被推导为int, 无视左右值
printV(3);// T被推导为int, 无视左右值

传const 引用

  • T会被推导为裸类型
  • 对于数组,会保留num的信息,且为数组类型
  • 无视左右值
  • 对于指针,最好不要传了,T会被推导int*, 但是int* const & par是啥已经有点看不懂了。
template<typename T>
void printV(const T& par)
{}
// demo
printV("hello");// T 被推导为char[6]
int a = 1;
int& b = a;
const int& c = a;
printV(a);// T被推导为int
printV(b);// T被推导为int
printV(c);// T被推导为int
int d[3] = {1,2,3};
printV(d);// T被推导为int[3]
const int e[3] = {1,2,3};
printV(e);// T被推导为int[3]
int num = 3;
printV(std::move(num));// T被推导为int, 无视左右值
printV(3);// T被推导为int, 无视左右值

传non-const引用

  • 不支持右值(这里有个bug, const修饰的可以)
  • 对于数组,数组保留num, 且为数组类型
    一般用非const的时候,都是想在函数里面把值给改了,但是第一条有一个bug, 就是可以传入一个const对象,这就比较难受,为此需要下面处理:
template<typename T>
void printV(T& par)
{}
std::string const c = "hello";
printV(c);//T会被推导为const string, 这样在模板里就不能改这个数字了,
//日,以后C++学习先背书好了,这么多乱其八糟都需要记住
//解决
template<typename T, typename dummy = enable_if_t<!std::is_const<T>::value> >
void printV(T& par);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值