拷贝构造函数

1. 拷贝构造函数

拷贝:将原来的对象里的内容重新复制一份,用原来的对象来初始化新的对象

如果用户没有显示的写出拷贝构造函数,那么编译器也会自动生成一个拷贝构造函数,如果用户显示的写出,那么编译器不会自动生成

拷贝构造函数又分为:深拷贝和浅拷贝

区分的前提:类中有指针变量需要去申请空间时,使用以后进行释放的操作

如果类中不含有指针去申请堆空间,那么深拷贝和浅拷贝没有区别

C语言:
	int  a=10;
	int  b=a;
C++:
	People  people1;
	People people2=people1;  //运算符重载,直接赋值拷贝,类似于C语言的形式

	拷贝构造:
	People  people1;
	People people2(people1); 

1.1 拷贝构造函数的原型:

类名  (const  类名  &  obj) //拷贝构造函数
	{

	}
例如:
	People(const People &obj)
	{

	}

2. 深拷贝

拷贝构造函数中,为指针重新开辟一块空间来存放值

copy_make.cpp

//深拷贝(类中变量涉及指针,并且有释放空间)
class People {
public:

	//构造函数
	People() {
		p = new int;//给指针p在堆区申请空间
	}

	//重写拷贝构造函数达到深拷贝的效果(一旦重写默认的拷贝构造函数将不再调用)
	//
	People(const People &obj) {
		//以下两行是深拷贝的核心思想,开辟 新空间,赋值
		//p = new int; //给people2中的p变量开辟新的空间,供对象结束后析构函数释放
		//*p = *(obj.p);//这里将people1中的p的值拷贝给 新的对象people2 中的p
		

		//这里是写成一行
		a = obj.a;//变量a的拷贝
		p = new int(*(obj.p));//指针p的拷贝,并且是新的空间  new int( );这个是带初始值的开辟空间,*(obj.p)是初始值

	}

	int a;//普通类型变量
	int* p;//指针变量

	//析构函数(在对象使用完毕后自动调用,用来释放对上的内存)
	//这里存在一个问题,因为p变量是个指针会在堆区开辟空间,在我的people1对象拷贝给people2对象后
	// ,people2对象中的p会和people1中的p指向同一个地址,但是析构函数的调用机制就是在一个对象使用完毕后自动调用,去释放指针占用的空间
	//然而people1调用的析构释放了p,但是people2结束后也会调用析构释放p,但是p已经被释放了,就会导致重复释放,然后出错
	//为了避免这种情况,要使用深拷贝
	~People() {//释放指针占用的空间
		delete p;
		//cout << "hello" << endl;
	}
};
int main()
{
	People people1;
	people1.a = 20;
	
	*(people1.p) = 30;
	//拷贝方法1用people1来初始化people2
	//People people2 = people1;//运算符重载
	
	//拷贝方法2,使用默认的拷贝构造函数
	People people2(people1);

	cout << " people1.a=" << people1.a << endl;
	cout << " people1.p=" << *(people1.p) << endl;
	cout << " people2.a=" << people2.a << endl;
	cout << " people2.p=" << *(people2.p) << endl;

	cout << endl;

	cout << " people1.a的地址" << &people1.a << endl;
	cout << " people2.a的地址" << &people2.a << endl;

	cout << endl;

	//这里再次改变a,p的值,people1改变不会影响people2,因为他们拥有不同的空间
	people1.a = 50;
	*(people1.p) = 60;
	cout << " people1.a=" << people1.a << endl;
	cout << " people1.p=" << *(people1.p) << endl;
	cout << " people2.a=" << people2.a << endl;
	cout << " people2.p=" << *(people2.p) << endl;

	return 0;
}

拷贝构造函数_第1张图片

3. 浅拷贝

拷贝时将原理对象中的成员变量的值拷贝一份到新的对象中

如果类中含有指针变量,并向堆区申请空间,那么使用浅拷贝会出现空间被重复释放造成程序崩溃的现象

copy_make.cpp

//浅拷贝
class People {
public:
	int a;//普通类型变量
};
int main()
{
	People people1;
	people1.a = 20;
	//拷贝方法1用people1来初始化people2
	//People people2 = people1;

	//拷贝方法2,使用默认的拷贝构造函数
	People people2(people1);

	cout << " people1.a=" << people1.a << endl;
	cout << " people2.a=" << people2.a << endl;

	cout << endl;
	
	cout << " people1.a的地址" << &people1.a << endl;
	cout << " people2.a的地址" << &people2.a << endl;

	cout << endl;

	//这里再次改变a的值,people1改变会影响people2,因为他们指向相同的空间
	people1.a = 20;
	cout << " people1.a=" << people1.a << endl;
	cout << " people2.a=" << people2.a << endl;
	return 0;
}

拷贝构造函数_第2张图片

4. 面试题:什么是浅拷贝?什么是深拷贝?

浅拷贝:

浅拷贝仅复制对象的成员变量的值,而不复制指向动态分配内存的指针

这意味着新对象和原对象共享相同内存地址,当一个对象的析构函数调用释放内存时, 可能影响另一个对象。

默认情况下,C++提供的复制构造函数和赋值运算符执行的是浅拷贝。

    深拷贝:

深拷贝会复制对象的所有内容,包括指向的动态分配内存。

这样,原对象和新对象拥有独立的内存,修改一个对象的数据不会影响到另一个对象

实现深拷贝通常需要自定义复制构造函数赋值运算符,以确保动态分配的资源被正确复 制。

5.  练习

拷贝构造函数_第3张图片

#define _CRT_SECURE_NO_WARNINGS  // 需要在 #include 前定义以禁用 C4996 警告
#include "iostream"

using namespace std;


//编写一个Person类,包括:
//1、普通数据成员 : 姓名, 性别,年龄。
//2、三个构造函数 : 无参数构造函数,有参数构造函数(参数 : 姓名的指针,年龄, 性别),拷贝构造函数。
//3、析构函数。
//4、输出人员信息函数print() 。
//编写main() 函数, 分别调用三种构造函数,创建三个对象P1、 P2、P3, 中P3的创建是用P2通过深拷贝复制得到的。

class Person {
public:
	char* name;
	char* sex;
	int age;

	//无参构造函数
	Person() {
		//给类中的属性赋初值
		name = new char[12];
		strcpy(name, "zhangsan");
		sex = new char[6];
		strcpy(sex,"male");
		age = 18;
	}

	//有参构造
	Person(const char* name1 ,const char* sex1,int age1) {

		// 为 name 和 sex 分配内存
		name = new char[12];
		sex = new char[8];

		strcpy(name, name1);
		strcpy(sex, sex1);
		age = age1;
	}

	//拷贝构造函数
	Person(Person &obj) {
		name = new char[strlen(obj.name)+1];
		sex = new char[strlen(obj.sex)+1];

		strcpy(name, obj.name);
		strcpy(sex, obj.sex);

		age = obj.age;
	}

	void print() {
		cout << "name=" << name << " age=" << age << " sex=" << sex << endl;
	}

	//析构函数
	~Person() {
		delete[] name;
		delete[] sex;
	}
};

int main()
{
	Person p1;
	p1.print();

	cout << endl;


	Person p2("lisi","female",22);
	p2.print();

	cout << endl;

	Person p3(p2);
	p3.print();

	return 0;
}

拷贝构造函数_第4张图片

你可能感兴趣的:(C++,c++,linux,c语言,算法)