C++赋值函数|移动赋值函数|移动构造函数

左值引用和右值引用

左值与右值:

左值:在内存中占有确定位置的对象,即左值占有内存。换句话来说,就是有地址,有值。

右值:不占内存(科学地讲是临时寄存器),仅有值,为临时变量。

左右值的切换:

右值->左值:用*符号。

int a=10;

int* b=&a;// b为右值。

*b=20;// b为右值,*b为左值。

左值->右值:用&符号。

int a = 10;

&a = 40;                  //错误:赋值操作要求一个左值
int* b = &(a + 1); //错误:‘&’运算符要求一个左值,a为左值,但a+1为右值。
int* c = &a;           //正确:var是左值

左值引用:将左值绑定在引用上。

第一种情况,函数返回右值。

int global = 10;
int test()
{
	return global;// 返回右值
}
int main()
{

	test() = 20;// error,右值不可赋值!
	cout << "test为:"<<test();
	return 0;
}

第二种情况,函数返回左值。

int global = 10;
int& test()
{
	return global;// 返回左值
}
int main()
{

	test() = 20;// 左值可赋值
	cout << "test为:"<<test();
	return 0;
}

测试:

说明了左值引用让函数调用可以赋值成为可能。

 常量左值引用和非常量左值引用:

int a1=20;              //非常量左值
const int a2=20;       //常量左值
const int a3=20;       //常量左值
 
//非常量左值引用
int &b1=a1;            //正确,a1是一个非常量左值,可以被非常量左值引用绑定
int &b2=a2;           //错误,a2是一个常量左值,不可以被非常量左值引用绑定
int &b3=20;           //错误,10是一个非常量右值,不可以被非常量左值引用绑定
int &b4=a2+a3;        //错误,(a2+a3)是一个常量右值,不可以被非常量左值引用绑定

//常量左值引用
const int &c1=a1;      //正确,a1是一个非常量左值,可以被非常量右值引用绑定
const int &c2=a2;     //正确,a2是一个常量左值,可以被非常量右值引用绑定
const int &c3=a1+a2;   //正确,(a1+a2)是一个非常量右值,可以被常量右值引用绑定
const int &c4=a2+a3;  //正确,(a2+a3)是一个常量右值,可以被非常量右值引用绑定

总结:

1.非常量左值引用只能绑定到非常量左值上;

2.常量左值引用可以绑定到非常量左值、常量左值、非常量右值、常量右值等所有类型。

(大->小,小引用绑大左值,常量左值范围更小嘛)

右值引用:将右值绑定在引用上。

常量右值引用和非常量右值引用:

int a1=20;             //非常量左值
const int a2=20;      //常量左值
const int a3=20;      //常量左值

//非常量右值引用
int &&b1=a1;            //错误,a1是一个非常量左值,不可以被非常量右值引用绑定
int &&b2=a2;           //错误,a2是一个常量左值,不可以被非常量右值引用绑定
int &&b3=20;           //正确,10是一个非常量右值,可以被非常量右值引用绑定
int &&b4=a2+a3;        //错误,(a2+a3)是一个常量右值,不可以被非常量右值引用绑定

//常量右值引用
const int &&c1=a1;      //错误,a1是一个非常量左值,不可以被常量右值引用绑定
const int &&c2=a2;     //错误,a2是一个常量左值,不可以被常量右值引用绑定
const int &&c3=a1+a2;   //正确,(a1+a2)是一个非常量右值,可以被常量右值引用绑定
const int &&c4=a2+a3;  //正确,(a2+a3)是一个常量右值,不可以被常量右值引用绑定

总结:

1.非常量右值引用只能绑定到非常量右值上;

2.常量右值引用可以绑定到非常量右值、常量右值上。

移动构造函数:

小狗狗类:

#include<string>
#include<iostream>
using namespace std;
class Dog
{
public:
	Dog(){};

	Dog(int age,string name) :m_age(new int(age)), m_name(name){}

	Dog(Dog& d):m_age(d.m_age),m_name(d.m_name) 
	{
		cout << "我是拷贝构造函数······" << endl;
	}
	Dog(Dog&& d) :m_age(d.m_age), m_name(d.m_name) 
	{
		d.m_age = nullptr;
		cout << "我是移动构造函数······" << endl;
	}

	int* m_age;
	string m_name;
};

 客户端类:

#include"construct.h"
int main()
{
	int age = 19;
	string name = "小狗狗";
	Dog d1(age, name);
	cout << "d1:" <<* d1.m_age << d1.m_name << endl;

	Dog d2(move(d1));

	bool is = d1.m_age == nullptr;
	cout << is << endl;

	cout << "d2.age:" << *d2.m_age <<endl<< "d2.name:" <<d2.m_name << endl;
	return 0;
}

测试:

 说明了移动构造运行成功,d1销毁了,d2获取到了d1的内存。

赋值和移动赋值函数:

赋值函数类:

#include<String>
using namespace std;
class Cat
{
public:
	Cat(){}
	Cat(int age ,string name):age(age),name(name) {}
	Cat& operator=(Cat& c)
	{
		if (this!= &c)
		{
			age = c.age;
			name = c.name;
		}
		return *this;
	}
	int age;
	string name;

};

 移动赋值函数类:

#include"assign.h"

class Dog
{
public:
	Dog() {}
	Dog(int age, string name) :age(new int(age)), name(name) {}

	Dog& operator=(Dog&& c)
	{
		age = c.age;
		name = c.name;
		c.age = nullptr;
		return *this;
	}
	int* age;
	string name;

};

客户端类:

#include<iostream>
#include"moveAssign.h"
int main()
{
	cout << "赋值函数" << endl;
	Cat c1(18, "小猫咪");
	Cat c2 ;
	c2 = c1;
	cout << "c1.age:" << c1.age << endl << "c1.name" << c1.name << endl;
	cout << "c2.age:" << c2.age << endl << "c2.name" << c2.name << endl<<endl;;

	cout << "移动赋值函数" << endl;
	Dog d1(19,"小狗狗");

	cout << "d1.age:" << *d1.age << endl << "d1.name" << d1.name << endl << endl;

	Dog d2;
	d2 = move(d1);
	bool is = (d1.age == nullptr);
	cout << "d1是否为空:" << is << endl;
	cout << "d2.age:" << *d2.age << endl << "d2.name" << d2.name << endl;
	return 0;
}

测试:

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值