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++#
全部评论

相关推荐

1.&nbsp;this指针是什么?它有什么作用?2.&nbsp;const成员函数有什么特点?如何使用?3.&nbsp;如何实现一个简单的动态数组?4.&nbsp;enum和enum&nbsp;class有什么区别?5.&nbsp;nullptr是什么?它与NULL有何不同?6.&nbsp;如何处理内存泄漏?请给出几种方法。7.&nbsp;解释一下数据库的ACID特性。8.&nbsp;什么是死锁?如何避免死锁?9.&nbsp;解释一下链表和数组的区别。10.&nbsp;什么是哈希表?它的优缺点是什么?11.&nbsp;如何使用SQL进行数据查询?请给出示例。12.&nbsp;什么是索引?它如何提高数据库查询性能?13.&nbsp;解释一下进程和线程的区别。14.&nbsp;什么是操作系统的中断机制?15.&nbsp;解释一下二叉树的遍历方式。16.&nbsp;如何实现一个简单的栈?17.&nbsp;什么是数据库范式?请简要说明第一范式和第二范式。18.&nbsp;解释一下内存管理中的堆和栈的区别。19.&nbsp;什么是SQL注入?如何防止它?20.&nbsp;解释一下快速排序和归并排序的基本原理。21.&nbsp;什么是视图(View)?它有什么用?22.&nbsp;如何使用std::vector实现动态数组?23.&nbsp;什么是事务?如何实现事务的提交和回滚?24.&nbsp;解释一下操作系统中的调度算法。25.&nbsp;如何实现一个简单的图结构?26.&nbsp;什么是外键?它的作用是什么?27.&nbsp;解释一下深度优先搜索和广度优先搜索的区别。28.&nbsp;什么是存储过程?它有什么优缺点?29.&nbsp;如何处理数据库中的并发访问?30.&nbsp;解释一下LRU缓存算法的基本原理。我面试看的是大佬的面经,链接放下边了&nbsp;&nbsp;c++/嵌入式面经专栏-牛客网 https://www.nowcoder.com/creation/manager/columnDetail/MJNwoM
点赞 评论 收藏
分享
评论
点赞
3
分享
牛客网
牛客企业服务