C++笔记——拷贝构造函数

拷贝构造函数

作用

用一个对象去初始化另外一个对象的时候就会自动调用拷贝构造函数

这是一个普通的 int 类型的初始化加赋值

int a=15;
 int b=a;

同样的道理

Animal a(6,60.5);
Animal b=a;  //调用拷贝构造函数

特点

  1. 没有重载形式
  2. 一定是用对象初始化另一个对象才调用
  3. 如果程序员没有定义拷贝构造函数,系统会自动帮你生成一个拷贝构造函数(浅拷贝)。如果程序员自定义析构函数,那么系统就不会再自动生成默认的析构函数
Animal(Animal &other)//浅拷贝 系统自动生成
{
    
    
	other中的数据赋值给this
}

语法规则

类名(类名 &)
{
    
    
	代码
}

实际例子

我们定义一个动物类,他的私有属性是年龄名字。然后创建一个对象a1,并给他初始化。然后定义一个对象a2,把a1的属性给他,看看会发生什么。

class Animal
{
    
    
public:
	Animal(int _age,const char *_name)//构造函数
	{
    
    
		age=_age;
		name=new char[20];//给私有成员name分配堆空间
		strcpy(name,_name);
		cout<<"构造函数调用了"<<endl;
	}
	
	void show()	//打印
	{
    
    
		cout<<"目前的对象是: "<<this<<endl;
		cout<<"它里面的数据,年龄是: "<<age<<"  名字是: "<<name<<endl;
	}
	
	void setattr(int newage,const char *newname)//修改私有成员
	{
    
    
		age=newage;
		strcpy(name,newname);
	}
	
private:
	int age;
	char *name;
};
int main()
{
    
    
	//创建对象
	Animal a1(5,"旺财");
	
	//创建另外一个对象
	Animal a2=a1;  //调用系统默认生成的拷贝构造函数,该函数有bug

	a1.show();
	a2.show();
}

在这里插入图片描述
可以看到a2的值与a1一样,看出了系统自动生成的拷贝函数是存在的。

但是如果我们修改a1的值,a2会有什么情况

//修改a1的属性
	a1.setattr(6,"阿黄");
	cout<<"================修改之后=============="<<endl;
	a1.show();
	a2.show();

在这里插入图片描述
明明修改a1的值为什么a2的名字也会跟着更改?

原因是我们的 a1.name 创建的时候用的是堆空间的内存,而当系统调用自动生成的拷贝函数的时候,只会为a2开辟栈空间的内存,a2.name的内存还是指向a1.name的堆空间。在这里插入图片描述
所以这就是系统生成的拷贝函数的缺点,称之为浅拷贝

深拷贝

Animal(Animal &other)
{
    
    
	this->age=other.age;
	this->name=new char[20]; //单独给当前对象的name指针分配独立的堆空间
	strcpy(this->name,other.name);
	cout<<"拷贝构造函数被调用"<<endl;
}

我们只要这样就能实现单独分开的效果。

浅拷贝之所以不能为新对象的属性分配堆空间,是因为它也不知道要分配多大,所以要程序员自行分配。

猜你喜欢

转载自blog.csdn.net/weixin_46026429/article/details/108509568