【C++】右值引用(极详细版)(三)

简介: 在讲右值引用之前,我们要了解什么是右值?那提到右值,就会想到左值,那左值又是什么呢?我们接下来一起学习!

这里运行后,我们看到调用了一次移动构造和一次移动赋值。

因为如果是用一个已经存在的对象接收,编译器就没办法优化了。mj::to_string函数中会先用str生成构造生成一个临时对象,但是我们可以看到,编译器很聪明的在这里把str识别成了右值,调用了移动构造。然后在把这个临时对象做为mj::to_string函数调用的返回值赋值给ret,这里调用的移动赋值。(直接资源交换)

总结:

2.对于插入右值数据时,也可以减少拷贝

只有左值引用时的插入接口:

入接口函数也增加了右值引用版本:

会直接进行资源交换,将将亡值和新创建的节点中的数据进行资源交换。


4.万能引用和完美转发

讲到这里,我们埋的伏笔也就要出来了:有左值引用,const左值引用;右值引用,但却没有提到const右值引用。


需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可

以取到该位置的地址。(右值被右值引用以后就成为了左值)

例如: 不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用。

int main()
{
  double x = 1.1, y = 2.2;
  int&& rr1 = 10;
  const double&& rr2 = x + y;
  rr1++;
  //rr2++;  //不可以修改
  cout << &rr1 << endl;
  cout << &rr2 << endl;
  return 0;
}

当然这个的具体应用场景在这里:

例如:

这里的移动构造和赋值构造,如果参数设为右值引用,那么作为右值如果不可以被修改,那资源的交换就不可以进行,所以这就是为什么,右值引用右值以后,就成为了左值。

情况二:

在我们自己模拟实现的list中,也实现插入接口是右值引用:

这就是在传右值时,右值引用会改变右值的特性,将其变为左值,那么需要不断move(左值)。

所以我们会想,有没有这么一个东西,自动去识别我们传的参数是左值还是右值,不会因为右值引用而改变右值属性。我们继续往下看

1.万能引用

当并不明确规定传右值或者左值时:

万能引用在这里起到了用处,可以随便传。(也叫做折叠)模板中的&&不是右值引用,而是为了万能引用,可以折叠。当传左值时,就把两个&&折叠为一个。同理可得

但是在继续调用Fun时,还是会因为属性导致结果并不是我们需要的:

走到调用fun(t)时,还是会因为右值引用导致右值变为左值,所以又出来了完美转发:

template<typename T>
void PerfectForward(T&& t)
{
  // t可能是左值,可能是右值
  //Fun(move(t));
  // 完美转发,保持他属性
  Fun(std::forward<T>(t));
  //t++;
}

很好的保持了属性。

所以在这里:

总结

右值引用的两个价值;

万能引用和完美转发

我们下期再见!

目录
相关文章
|
7月前
|
算法 编译器 程序员
【C/C++ 解惑 】 std::move 将左值转换为右值的背后发生了什么?
【C/C++ 解惑 】 std::move 将左值转换为右值的背后发生了什么?
92 0
|
7月前
|
C++
c++左值和右值,左值引用和右值引用
c++左值和右值,左值引用和右值引用
60 0
|
28天前
|
存储 安全 C++
【C++11】右值引用
C++11引入的右值引用(rvalue references)是现代C++的重要特性,允许更高效地处理临时对象,避免不必要的拷贝,提升性能。右值引用与移动语义(move semantics)和完美转发(perfect forwarding)紧密相关,通过移动构造函数和移动赋值运算符,实现了资源的直接转移,提高了大对象和动态资源管理的效率。同时,完美转发技术通过模板参数完美地转发函数参数,保持参数的原始类型,进一步优化了代码性能。
34 2
|
3月前
|
编译器 C++
C++ 11新特性之右值引用
C++ 11新特性之右值引用
54 1
|
7月前
|
编译器 C语言 C++
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值(中)
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值
42 1
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值(中)
|
7月前
|
存储 安全 C语言
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值(上)
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值
38 2
|
7月前
|
编译器 C语言 C++
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值(下)
从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值
45 1
|
6月前
|
编译器 C++ 开发者
C++一分钟之-右值引用与完美转发
【6月更文挑战第25天】C++11引入的右值引用和完美转发增强了资源管理和模板灵活性。右值引用(`&&`)用于绑定临时对象,支持移动语义,减少拷贝。移动构造和赋值允许有效“窃取”资源。完美转发通过`std::forward`保持参数原样传递,适用于通用模板。常见问题包括误解右值引用只能绑定临时对象,误用`std::forward`,忽视`noexcept`和过度使用`std::move`。高效技巧涉及利用右值引用优化容器操作,使用完美转发构造函数和创建通用工厂函数。掌握这些特性能提升代码效率和泛型编程能力。
57 0
|
7月前
|
编译器 C++ 容器
【C++11(一)】右值引用以及列表初始化
【C++11(一)】右值引用以及列表初始化
|
7月前
|
存储 安全 程序员
C++11:右值引用
C++11:右值引用
48 0