c++中std::move的简单理解

在程序中,经常会碰到内存的申请和释放。比如对某个对象的复制,有时是对该对象的复制,当对象所占内存空间很大时,需要新申请一个相同大小的内存空间,造成内存的浪费。这里的std::move()是完成对象的移动功能。在需要的时候可以节省很大内存。

1左值和右值的区别

  • 左值可以当作右值使用,但是右值不能当作左值使用。
  • 左值是一个对象,而右值是一个对象的值。
  • 右值引用指向将要销毁的对象。
  • 右值引用通常不能直接绑定到任何左值上面,但是可以使用move函数进行转换

std::move()的使用是简单的,这里分析一下程序的内部进程。首先是理解左值和右值的区别。一般左值是一个对象,右值是对象的值。

左值引用:引用一个对象,int i = 0;  int &j = i;

右值引用:为了支持移动操作,新标准引入了一种新的类型----->右值引用,所谓右值引用就是必须绑定到右值的引用。我们通过&& 而不是&来获得右值引用。右值引用只能绑定到一个将要销毁的对象上面。有着完全相反的绑定特性,我们可以将一个右值引用绑定到这类表达式上,但是不能将一个右值引用直接绑定到左值上。

int i  = 42; 
int &r = i;      //正确,r引用i,是一个左值引用
int &&rr = i;    //错误,不能将一个右值引用绑定到一个左值上。
int &r2 = i * 42;    //错误,i*42是一个右值
const int &r3 = i *42; //正确,可以将一个const的引用绑定到一个右值上
int &&rr2 = i * 42;     //将rr2绑定到乘法结果上

2 引用折叠

下面是定义的规则:在类似与T&&&&&&&&&&&中,1--3个&&折叠成一个&,2--5个&折叠成两个&&

3 模板中的类型推断规则

       remove_reference是一个模板,有一个模板参数和一个type的public成员。

标准类型转换模板
Mod<T>若T为则Mod<T>::type 为
remove_reference

X&或X&&

否则

X

T

4  std::move()的理解

/*源代码*/
template <typename T>
typename remove_reference<T>::type&& move(T&& t)
{
	return static_cast<typename remove_reference<T>::type&&>(t);
}

首先形参是T&&的右值引用类型,这里对实参的推断如下

  1. 实参是右值时,T为被引用的类型
  2. 实参是左值时,T为引用类型。
string s1("hi!"),s2;
s2 = std::move(string("bye"));
s2 = std::move(s1);//左值

在第一个赋值中,传递给move的实参是右值,向一个右值引用传递一个右值,由实参推断出的类型为引用的类型。

  1. 推断出的T为:string
  2. remove_reference<string>的type成员 是string
  3. move的返回类型是string&&
  4. move的函数参数t的类型为string&&
  5. 即函数string&& move(string &&t)

在第二个赋值中,传递给move的实参是左值,

  1. 推断出T的类型为string&
  2. 因此,remove_reference用string&进行实例化
  3. type成员的类型是string
  4. move的返回类型是string&&
  5. move的函数参数t是string & &&,会折叠成string&
  6. 即调用:string&& move(string &t),static_cast<string&&>(t),强制将t转换为string&&

版权声明:本文为qq_24279775原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。