C++ std::move原理&右值引用存在的必要性

在学习C++的过程中一直搞不懂为什么要存在右值引用,将左值引用变为右值引用


个人认为就是减少拷贝构造,赋值重载过程内存开辟拷贝的次数,提高速度


我们现在看一段代码:

#include <iostream>
#include <cstring>
using namespace std;


class Student{

	friend class Teacher;
private:

	char * pStart;
	int length;

public:


	Student(char* p = nullptr){
		cout << "contructer" << endl;
		if(p == nullptr){
			this->pStart = nullptr;
			this->length = 0;
	   }else{
		   this->length = strlen(p) +1;
		   this->pStart = new char[this->length];
		   strcpy(this->pStart,p);
		}
	}


	Student(const Student& stu){
		cout << "copy constructer" << endl;
		this->length = stu.length;
		this->pStart = new char[this->length];
		strcpy(this->pStart,stu.pStart);
	
	}

	void operator=(const Student& stu){
     
		cout << "== coonstructer"<< endl;
		if(this->pStart != nullptr){
			delete[] this->pStart;
		}
  	    
		this->length = stu.length;
		this->pStart = new char[this->length];
		strcpy(this->pStart,stu.pStart);

	}


	~Student(){
		cout << "delete" << endl;
		if(this->pStart != nullptr){
			delete[] this->pStart;
			this->pStart = nullptr;
		}
	
	}

	friend ostream& operator<<(ostream& cout,const Student&stu){
		cout << "value = " << stu.pStart << endl;
		return cout;
	}

};
Student funcTest(){

	Student stu("Beijing");
	return stu;



Studnt类里面有个字符串成员变量,我们每次在进行拷贝 赋值的时候都要进行开辟内存,拷贝数据的过程。

funcTest()函数会返回Student对象。当我们调用stu = funcTest()的时候:

1:Student stu("Beijing")会调用一次构造函数

2:由于函数执行完会释放栈上的内存,所以stu会被析构,但是要将stu作为返回值返回,编译器会创建一个临时对象(通过拷贝stu实现),这个临时对象不再内存中

      就是我们常说的右值,可以理解为在CPU的寄存器中。左值 很粗的理解就是在内种中特定存在的.

3:stu会对临时对象(右值)进行拷贝构造

总结:stu = funcTest()一共会调用1次构造,1次拷贝,1次右值重载

看函数调用结果:

void main(){

	Student stu3("beijing");
	stu3 = funcTest();
	cin.get();

}



下面考虑一个问题这个我们知道函数funTest()返回Student其实是一个临时对象,这个临时对象用一次就被析构了,赋值重载过程中能不能将指针指向临时对象的内存,减少内存开辟拷贝的过程。

下面我们就要引出右值引用的代码了:

Teacher(Student&& stuparam){
		cout << "右值引用"<< endl;
		stu.length = stuparam.length;
		stu.pStart = stuparam.pStart;
		stuparam.pStart= nullptr;
	}


我们看到将指针指向临时对象的内存就可以不用开辟内存了, 但是为什么要将临时对象的pStart变成nullptr?因为这个临时对象会立刻被析构,如果不变成nullptr,我们再次访问pStart的时候,指向的内存因为析构了变成垃圾值了。具体看代码


Student stu3("beijing");
	stu3 = funcTest();
    cout << "==============================" << endl;

执行结果:



如果右值引用的代码变成这样:

void operator=(Student&& stu2){
	   cout << "右值拷贝"<< endl;
	   if(this->pStart != nullptr){
			delete[] this->pStart;
		}
	   this->pStart = stu2.pStart;
	   this->length = stu2.length;
	   //stu2.pStart = nullptr;
	   
	}

执行结果:




下面在通过一段代码来巩固一下右值引用的作用到底有多大

class Teacher{

private:
	Student stu;
public:
	Teacher(const Student& stuparam){
		cout << "左值引用" << endl;
 	   stu = stuparam;
	}

	Teacher(Student&& stuparam){
		cout << "右值引用"<< endl;
		stu.length = stuparam.length;
		stu.pStart = stuparam.pStart;
		stuparam.pStart= nullptr;
	}

	void test(){
	   cout << stu << endl;
	}

};

void main(){

	//Sdudent("12222")临时对象也就是右值
	Teacher t(Student("12222"));
	t.test();

	cin.get();

}

执行结果如图:



void main(){

	Student stu2("Nanjing By Zhongqi.Shao");
	//Sdudent("12222")临时对象也就是右值
	Teacher t(stu2);
	t.test();

	cin.get();

}


void main(){

	Student stu2("Nanjing By Zhongqi.Shao");
	//Sdudent("12222")临时对象也就是右值
	Teacher t(std::move(stu2));
	t.test();

	cin.get();

}

结果如下:



到这你就明白为什么要std::move(leftValue)了吧,以及明白了右值引用到底做了什么了 哈哈哈 。。。。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值