关于左值,右值(移动语法 &&和std::move)

首先是移动语法。

int&&和int&类型的主要区别有以下几点:

  1. 引用类别
  • int&是左值引用,只能绑定到左值上,即具名对象。

  • int&&是右值引用,可以绑定到右值和左值。

  1. 绑定对象
  • int&必须绑定到一个已经存在的对象(左值)上。

  • int&&可以绑定到一个临时对象(右值)上。

  1. 移动语义
  • int&不支持移动语义,传值时总是复制对象。

  • int&&支持移动语义,传值可以直接移动而不是复制对象。

  1. 传参方式
  • int&常用于引用传参,以避免复制对象。

  • int&&一般用于传值的场景,实现高效移动操作。

  1. 对象生命周期
  • int&绑定的对象在绑定作用域外仍然有效。

  • int&&绑定的临时对象生命周期结束被销毁。

所以总结来说:

int&是左值引用,int&&是右值引用。
int&用于引用传参,int&&用于实现移动语义的传值操作。
int&&支持移动临时对象的资源。

两者在语义和使用场景上有明显差异。

int&&用法举例

“int&&支持移动语义,传值可以直接移动而不是复制对象”,具体来说指:

  • 对于一个临时对象(右值),如果将它直接传值传递给一个函数,会触发其拷贝构造函数进行值拷贝。

  • 而如果参数声明为右值引用int&&,就可以利用C++11新增的移动语义。

  • 移动语义允许直接移动临时对象的内容,而不是复制其值。这避免了不必要的拷贝操作。

举个例子:

void func(int value){
  // value被值拷贝 
}

int main(){
  int temp = 10;
  func(temp); // temp被拷贝
}

即便temp是一个临时对象,它也会被拷贝一份。

而使用右值引用:

void func(int&& value){
  // value移动而非拷贝
}

func(10); // 直接移动10而非拷贝

这里10是一个临时对象,通过右值引用就可以直接移动其值到func,而不是复制一个临时副本。

所以总体来说,int&&能利用C++11移动语义特性,直接移动临时对象内存而不是值拷贝,从而提高效率。

std::move()

传入

如果func函数的参数是变量a,而不是一个临时数值,那么是否需要加std::move取决于以下情况:

  • 如果a是泛指的变量,既可能是右值也可能是左值,此时需要加std::move:
int a = 10;
func(std::move(a)); 

std::move将a转换为右值引用,以使用移动语义传递。

  • 如果明确声明a是左值,如常量引用,此时不需要std::move:
int a = 10;
const int& ref = a;
func(ref);

ref是一个左值引用,直接传递可以使用移动语义。

  • 如果a是函数参数而不是变量,也不需要std::move:
void bar(int a) {
  func(a); 
}

参数a已经是右值,直接使用移动语义。

总之:

  • 如果参数本身就是右值,无需std::move。

  • 如果参数可能是左值,使用std::move强制转换为右值传递。

  • 如果参数是常量引用/引用类型的左值,也无需std::move。

所以是否需要std::move,关键看参数本身是左值还是右值。

传出

如果在func函数中,想将右值引用参数value的值赋给一个变量b,此时是否需要std::move如下:

  • 如果b是右值引用类型(int&& b),则不需要std::move:
void func(int&& value){
  int&& b = value; //直接赋值,实现移动语义
}
  • 如果b是普通变量(int b),这里需要std::move:
void func(int&& value){
  int b = std::move(value); //b是左值,value右值,需要std::move
}

这是因为:

  • value作为参数是右值引用,表示可以直接移动其值。

  • 但赋值给普通变量b时,b是左值,value作为右值无法直接访问其内存。

  • 使用std::move可以将value从右值引用转换为纯右值,使得其值可以被移动给左值b。

所以总结来说:

  • 如果目标是右值引用,不需要std::move直接赋值即可移动;

  • 如果目标是普通变量(左值),需要std::move将源转换为右值以支持移动操作。

这是因为std::move的作用就是值类别转换,支持值之间的移动语义传递。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11中,有两个重要的函数std::forward和std::move。 std::forward函数: std::forward函数是用来解决转发参数类型的问题的。当我们在编写一个函数模板时,如果需要将参数转发给另一个函数时,我们需要使用std::forward函数来将参数正确地转发过去。std::forward函数的定义如下: template <class T> constexpr T&& forward(typename std::remove_reference<T>::type& x) noexcept; template <class T> constexpr T&& forward(typename std::remove_reference<T>::type&& x) noexcept; std::forward函数的作用是将一个参数转发给另一个函数,同时保留该参数的原始类型(左值右值)。当我们需要将一个参数转发给另一个函数时,我们通常需要使用std::forward函数来实现类型转发。例如: template <typename T> void foo(T&& arg) { bar(std::forward<T>(arg)); } std::move函数: std::move函数用于将一个对象的值转移到另一个对象中,同时将原始对象的值置为未定义状态。std::move函数的定义如下: template <class T> typename std::remove_reference<T>::type&& move(T&& x) noexcept; std::move函数的作用是将一个对象的值转移到另一个对象中,同时保留该对象的原始类型(左值右值)。当我们需要将一个对象的值转移到另一个对象时,我们通常需要使用std::move函数来实现。例如: std::vector<int> v1 = {1, 2, 3}; std::vector<int> v2 = std::move(v1); // v1现在是未定义状态,v2的值为{1, 2, 3}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值