C++之对象的赋值与复制(拷贝构造函数)

十一!!!!学习
一、对象赋值语句
这里所指的对象的赋值是指对其中的数据成员赋值,而不对成员函数赋值。
例如:A和B是同一类的两个对象,那么下述对象赋值语句B=A就能把对象A的数据成员的值逐位赋值给对象B

#include<iostream>
using namespace std;
class Myclass
{
private:
	int a,b;
public:
	void set(int i,int j)
	{
		a=i;
		b=j;
	}
	void show()
	{
		cout<<a<<" "<<b<<endl;
	}
};
int main()
{
	Myclass o1,o2;
	o1.set(20,5);
	o2=o1;
	o1.show();
	o2.show();
	return 0;
}
运行结果:
20 5
20 5

说明:
(1)在使用对象赋值语句进行对象赋值时,两个对象的类型必须相同,如对象的类型不同,编译时将出错。
(2)两个对象之间的赋值,仅仅使这些对象中数据成员,而两个对象仍是分离的。
(3)对象赋值是通过默认赋值运算符函数实现的。
(4)将一个对象的值赋给另一个对象时,多数情况下都是成功的,但当类中存在指针时,可能会产生错误。

二、拷贝构造函数
是一种特殊的构造函数,其形参是本类对象的引用,其形参是本类对象的引用。作用是,在建立一个对象时,使用一个已经存在的对象去初始化这个新对象。
特点:
(1)因为该函数也是一种构造函数,所以其函数名与类名相同,并且该函数也没有返回值类型。
(2)该函数只有一个参数,并且是同类对象的引用
(3)每个函数都必须有一个拷贝构造函数。可以自定义拷贝构造函数,用于按照需要初始化新对象。如果没有定义类的拷贝构造函数,系统就会自动生成一个默认拷贝构造函数,用于复制出数据成员值完全相同的新对象。
1.自定义拷贝构造函数
形式如下:
类名::类名(const 类名 &对象名)
{
// 拷贝构造函数的函数体
}

#include<iostream>
using namespace std;
class Point
{
private:
	int x,y;
public:
	Point(int a,int b)//普通构造函数
	{
		x=a;
		y=b;
	}
	Point(const Point &p)//自定义的拷贝构造函数
	{
		x=2*p.x;
		y=2*p.y;
	}
	void print()
	{
		cout<<x<<" "<<y<<endl;
	}
};
int main()
{
	Point p1(30,40);//定义对象p1,调用了普通的构造函数
	Point p2(p1);//调用拷贝构造函数,用对象p1初始化对象p2
	p1.print();
	p2.print();
	return 0;
}
运行结果:
30 40
60 80

2.调用拷贝构造函数的一般形式为:
(1)代入法:
类名 对象2(对象1);
如:Point p2(p1);
(2)赋值法:
类名 对象2=对象1;

#include<iostream>
using namespace std;
int main()
{
	Point p1(10,20);
	Point p2=p1;
	p1.print();
	p2.print();
	return 0;
}

2.默认拷贝构造函数
每个类都必须有一个拷贝构造函数,如果未定义,系统自动生成一个默认拷贝构造函数

class Point
{
private:
	int x,y;
public:
	Point(int a,int b)//构造函数
	{
		x=a;
		y=b;
	}
	void print()
	{
		cout<<x<<" "<<y<<endl;
	}
};
int main()
{
	Point p1(30,40);//定义类Point的对象p1,调用了普通构造函数
	Point p2(p1);//用代入法调用默认拷贝构造函数,用p1初始化p2
	Point p3=p1;//用赋值法调用默认拷贝构造函数,用对象p1初始化对象p3
	p1.print();
	p2.print();
	p3.print();
	return 0;	
}

3.调用拷贝构造函数的3种情况
(1)当用类的一个对象去初始化该类的另一个对象时,拷贝构造函数将会被调用。

Point p2(p1);//用代入法调用拷贝构造函数,用对象p1初始化对象p2
Point p3=p1;//用赋值法调用拷贝构造函数,用对象p1初始化对象p3

(2)当函数的形参是类的对象,在调用函数进行形参和实参结合时,拷贝构造函数将会被调用。

void fun1(Point p)//形参是类Point的对象p
{
p.print();
}
int main()
{
Point p1(10,20);
fun1(p1);//调用函数fun1时,实参p1是类Point的对象
return 0;//将调用拷贝构造函数,初始化形参对象p
}

(3).当函数的返回值是类的对象,在函数调用完毕将返回值(对象)带回函数调用处时。此时就会调用拷贝构造函数,将此对象复制给一个临时对象并传到该函数的调用处。
例如:

Point fun2()//函数fun2的返回值类型是Point类类型
{
   Point p1(10,30);//定义类Point的对象
   return p1;//函数的返回值是Point类的对象
}
int main()
{
 Point p2;//定义类Point的对象
 p2=fun2();//函数执行完成,返回调用者时,调用拷贝构造函数
 return 0;
}

由于对象p1是在函数fun2中定义的,在调用函数fun2结束时,p1的生命周期结束,因此在函数fun2()结束前,这个临时对象时编译系统在主程序中临时创建的。函数运行结束时对象p1消失,但临时对象将会通过语句“p2=fun2()”将它的值赋给对象p2.执行语句完成后,临时对象的使命也就完成了,该临时对象便自动消失。
4.演示调用拷贝构造函数的3种情况

#include<iostream>
#include<Windows.h>
using namespace std;
class Point 
{
public:
	Point (int a0,int b=0);//声明构造函数
	Point(const Point &p);//声明拷贝构造函数
	void print()
	{
		cout << x << " " << y << endl;
	}
	
private:
	int x,y;
};

Point ::Point (int a,int b)
{
	x = a;
	y = b;
	cout << "Using normal constructor\n";
}
Point::Point(const Point &p)//定义拷贝构造函数
{
	x = 2 * p.x;
	y = 2 * p.y;
	cout << "Using copy constructor\n";
}
void fun1(Point p)//函数fun1的形参是类对象
{
	p.print();
}
Point fun2()
{
	Point p4(10, 30);//定义对象p4时,要调用普通的构造函数
	return p4;//返回对象p4时,要调用拷贝构造函数
}
int main()
{
	Point p1(30, 40);//定义对象p1时,第一次调用普通的构造函数
	p1.print();
	Point p2(p1);//建立新对象p2时,第一次调用拷贝构造函数,用对象p1初始化对象p2
	p2.print();
	Point p3 = p1;//用对象p1初始化p3
	p3.print();
	fun1(p1);//在调用函数fun1,实参和形参结合时,第三次调用拷贝构造函数
	p2 = fun2();//在调用fun2时,第二次调用普通的构造函数,当fun2结束时,第四次调用拷贝构造函数
	p2.print();
	system("pause");
	return 0;
}

运行结果:

在这里插入图片描述

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值