C++赋值运算符重载 &&拷贝构造和赋值运算符重载区别

对于一个类,本身应该有四个默认函数:

1.默认构造

2.默认析构

3.拷贝构造

4、默认赋值运算符operator= (赋值运算符重载函数)

赋值运算符重载函数与拷贝构造函数一样,都是对类的属性进行值拷贝。

#include
using namespace std;

class Person
{

	friend ostream& operator<<(ostream& cout, Person p);
public:
	Person(){}
	Person(int a) {

		this->A = a;

	}

	//拷贝构造
	Person(const Person& p) {
		this->A = p.A;
	}

	//赋值
	void operator=(const Person &p) {
		this->A = p.A;
		
	}
	


private:
	
	int A;
};

//重载左移运算符
ostream& operator<<(ostream &cout,Person p) {
	cout << "A=" << p.A;
	return cout;
}
void test01()
{
	Person p1(0);
	Person p2(1);
	p2 = p1; //赋值
	Person p3(p1); //拷贝构造
	cout << "p1=" << p1 << endl;
	cout << "p2=" << p2 << endl;
	cout << "p3=" << p3 << endl;

}

int main()
{
	test01();

	return 0;
}

但是两个函数却有些许不同

区别:
拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象;但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而赋值运算符是将对象的值复制给一个已经存在的实例。这种区别从两者的名字也可以很轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生。如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。

另外,赋值运算符重载函数有一个特性,那就是可以有返回值。因此可以同时对多个类进行赋值。
 

代码:

#include
using namespace std;

class Person
{

	friend ostream& operator<<(ostream& cout, Person p);
public:
	Person(){}
	Person(int a) {

		this->A = a;

	}

	//拷贝构造
	Person(const Person& p) {
		this->A = p.A;
	}

	//赋值
	Person& operator=(const Person &p) {
		this->A = p.A;
		return *this;  //可以有返回值
	}
	


private:
	
	int A;
};

//重载左移运算符
ostream& operator<<(ostream &cout,Person p) {
	cout << "A=" << p.A;
	return cout;
}
void test01()
{
	Person p1(0);
	Person p2(1);
	Person pp(2);
	
	p2 = p1 = pp;  //可以对多个类同时进行赋值

	Person p3(p1); //拷贝构造
	cout << "p1=" << p1 << endl;
	cout << "p2=" << p2 << endl;
	cout << "p3=" << p3 << endl;
	cout << "pp=" << pp << endl;

}

int main()
{
	test01();

	return 0;
}

同拷贝构造函数一样,赋值运算符重载函数也会发生深浅拷贝问题。在类与类之间进行赋值时,发生浅拷贝问题的时候,也要进行深拷贝。不过在进行深拷贝操作的时候,会略有不同。

代码:

#include
using namespace std;

class Person
{

	friend ostream& operator<<(ostream& cout, Person p);
public:
	Person(){}
	Person(int a) {

		this->A = new int(a);

	}

	//拷贝构造
	Person(const Person& p) {
		//this->A = p.A;  //浅拷贝

		//不需要释放内存

		//深拷贝
		A = new int(*p.A);
	}

	

	//赋值
	Person& operator=(const Person &p) {
		//this->A = p.A;  //浅拷贝

		
		if (this->A != NULL) {  //应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
			
			delete A;
			A = NULL;
		}
		//深拷贝

		A = new int(*p.A); 

		return *this;  //可以有返回值
	}
	
	~Person() {  //堆区数据手动开辟,需要手动释放,因此需要调用析构函数。此时发生浅拷贝问题
		if (A != NULL) {
			delete A;
			A = NULL;
		}
	}


private:
	
	int *A;
};

//重载左移运算符
ostream& operator<<(ostream &cout,Person p) {
	cout << "A=" << *p.A;
	return cout;
}
void test01()
{
	Person p1(0);
	Person p2(1);
	Person pp(2);
	
	p2 = p1 = pp;  //可以对多个类同时进行赋值

	Person p3(p1); //拷贝构造
	cout << "p1=" << p1 << endl;
	cout << "p2=" << p2 << endl;
	cout << "p3=" << p3 << endl;
	cout << "pp=" << pp << endl;

}

int main()
{
	test01();

	return 0;
}

可以看到,在赋值运算符重载函数进行深拷贝之前,我们要先进行清理内存操作,再进行深拷贝。和拷贝构造函数创建新对象进行拷贝不同,赋值运算符是执行某种运算,将一个对象的值复制给将一个对象的值复制给另一个对象(已经存在的),因此我们要对已有的对象属性进行赋值,必须先清理掉已有的对象属性再赋值,这样就不会造成内存泄漏。

你可能感兴趣的:(C++,c++,开发语言)