C++面试题:万能引用与右值引用的区别

alt 为了更好地理解模版,你需要知道万能引用,在模版推导中,它有着特殊的规则。在这篇文章里,我将教你区分万能引用和右值引用。

定义:万能引用可用于绑定左值和右值,只会出现在模版函数的入参中或者auto的推导中;右值引用只能用于绑定右值。例子如下:

void f(Widget&& param); // 右值引用
Widget&& var1 = Widget(); // 右值引用
auto&& var2 = var1; // 万能引用!!!
template<typename T>
void f(std::vector<T>&& param); // 右值引用
template<typename T>
void f(T&& param); // 万能引用

注:万能引用可以绑定左值,也可以绑定右值,还可以绑定const对象、volatile对象、const volatile对象,而右值引用只能绑定右值,不能绑定左值。例子如下:

// 万能引用
template<typename T>
void f(T&& param); // 万能引用
int x = 27;
const int cx = x;
const int& rx = x;
f(cx); // T的类型是const int&,param类型也是const int&
f(rx); // T的类型是const int&,param类型也是const int&
f(27); // T的类型是int,param类型是int&&

要使一个引用成为万能引用,其涉及类型推导是必要条件,但不是充分条件。比如:形如“T&&”也必要条件(包括auto和参数化模板),但是在T&&中加上const就不是万能引用了。以下例子:

// 有类型推导,但是是右值引用
template<typename T>
void f(std::vector<T>&& param); // 右值引用
std::vector<int> v;
f(v); // 错误,右值引用不能绑定左值!!

// 加了cosnt饰词后是右值引用
template<typename T>
void f(const T&& param); // param是右值引用!!!!!

但即使位于模板内的“T&&”,也有可能不是万能引用。

template<class T, class Allocator = allocator<T>>
class vector {
public:
  void push_back(T&& x); // 不是万能引用。
};
std::vector<Widget> v; // 因为声明vector这个class后,T就具象化了,所以上面是一个右值引用!!

万能引用可以用于Args&&...args这种参数化模板。

template<class T, class Allocator = allocator<T>>
class vector {
public:
  // Args是独立于vector的型别形参T的参数包。
  template<class... Args>
  void emplace_back(Args&&... x); // Args中每一个参数都是万能引用!!
};

auto&&是万能引用,因为它自带型别推导。

auto timeFuncInvocation = 
  [](auto&& func, auto&&... params) { // auto&&用于lambda的形参推导!!
  // forward+decltype的组合
  // 调用func,取用params。
  std::forward<decltype(func)>(func)(
    std::forward<decltype(params)>(params)); // 见条款33
};

聊完以上知识点,感觉自己的C++技能又提升了一点。希望以上剖析的思路,能有效地帮助你学习以下经典C++书籍。

alt

#C++#
全部评论

相关推荐

问的很有深度呐,二面就更注重整个项目的实现与理解了,包括一些算法,比一面的压力大了很多,最终得到的评价是比较不错的,项目都能说的清楚做了什么,怎么实现。不过才27,一些深层的不了解问题不算太大....(最后还是横向了好几天,在最后我快要接受失败时,等来了hr的电话!)反问环节面试官表示对实习生的期望是尽可能独挡一面,能快速上手业务。于是乎一激动我直接说在第一段实习时,第一天下午就开干!(面试官表示很震惊)543个日夜,取得了阶段性的胜利1.&nbsp;自我介绍与项目背景简单做个介绍这几个项目经历都是在学校自己做的吗?你从什么时候开始接触相关开发的?是学的课程吗?你是一般通过什么方式学习的?2.&nbsp;项目深入探讨LRU组件:你第一个项目里面,又做了一个开发的组件,这主要是解决什么问题的,怎么做的?缓存原因:为什么要对组件缓存?缓存组件类型:都有哪些组件,需要多少个?组件定义:这个组件是个什么组件?缓存选择:你为啥不直接存储数据,而是直接保存组件呢?缓存数量:你这样缓存,你会缓存多少个组件?3.&nbsp;算法与数据结构LRU实现:LRU你怎么实现的?具体实现:如果让你实现一个LRU你会怎么实现?链表类型:你需要用什么链表?单向的吗?你看一下单向能解决问题吗?双向链表:为什么要用双向?时间复杂度:那这个时间复杂度会是多少?查找优化:找的话遍历是O(n),有没有更快的办法?Map作用:Map这个Map是干啥的?4.&nbsp;网络协议与通信Protobuf使用:我看你还是用Protobuf,然后是现在机制的是吧?为什么用这个?心跳包定义:这个心跳包指的什么?自实现确认:这个心跳机制是你自己实现的是吧?数据量问题:你原来的传播数据量大吗?一个心跳的话为啥数据量会大?5.&nbsp;框架对比与选择React&nbsp;vs&nbsp;Vue:你学过React、也学过Vue,是吧?他们俩有啥区别?什么时候用哪个?他们的缺点是什么?状态管理:原来可能是怎么做状态管理的?(指Redux、Zustand等)全局变量对比:我用全局变量行吗?为什么一定要状态管理呢?功能需求:比方说我需要有啥功能?库选择:你为什么选Zustand这个库?还有哪些库?Redux了解:里边有Redux吗?6.&nbsp;计算机基础多线程概念:多线程之前了解过吗?线程同步:有哪些常见的线程同步的技术?比方说多个线程访问同一个变量或互斥区,有哪些保持同步和互斥的手段?7.&nbsp;网络安全HTTPS机制:HTTPS了解吗?它到底是一个什么样的一个工作机制?8.&nbsp;算法编程编码题:有两个有序数组[1,3,5,7]和[2,3,6,8],合并成一个有序数组[1,2,3,5,6,7,8],重复元素只保留一个算法思路:说一下算法的思路代码实现:能不用现成的API,直接用算法去写吗?哎呀,要是多问问我实习就好了,还是一面扯太多了哈哈好怀念第一段实习呐,真的很锻炼人......希望在滴滴能一切顺利
我的实习求职记录
点赞 评论 收藏
分享
评论
1
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务