拷贝构造函数:对象复制的重要工具

2023-12-07 13:36:14 浏览数 (1)

拷贝构造函数

功能: 使用一个已经存在的对象来初始化一个新的同一类型的对象。 声明: 只有一个参数并且参数为该类对象的引用 如果类中没有说明拷贝构造函数,则系统会自动生成一个缺省复制构造函数,作为该类的公有成员。

当函数的形参是类的对象,调用函数时,进行形参与实参结合时便用。 这时要在内存新建立一个局部对象,并把实参拷贝到新的对象中。理所当然也调用拷贝构造函数。

代码语言:javascript复制
  1 #include"copy.h"
  2 /*void function(const person& p)
  3 {
  4     cout<<"constructor"<<endl;
  5 }*/
  6 void function2(const person p)
  7 {
  8     cout<<"constructor"<<endl;
  9 }
 10 
 11 int main()
 12 {
 13     person p(10,20);
 14     person pp(p);
 15     person ppp = pp;
 16 
 17     function2(p);
 18     return 0;
 19 }

结果:

代码语言:javascript复制
[bsk@localhost structor]$ ./a.out 
person constructor //p的默认构造调用
copy function10  //pp的拷贝构造调用
copy function10 //ppp的拷贝构造调用
copy function10 //function函数拷贝构造
constructor

那如果函数参数时以引用的方式,会不会调用拷贝构造函数呢?

代码语言:javascript复制
  1 #include"copy.h"
  2 void function(const person& p)
  3 {
  4     cout<<"constructor"<<endl;
  5 }
  6 int main()
  7 {
  8     person p(10,20);
  9     person pp(p);
 10     person ppp = pp;
 11 
 12     function(p);
 13     return 0;
 14 }

结果如下:

代码语言:javascript复制
[bsk@localhost structor]$ ./a.out 
person constructor //p的默认构造调用
copy function10  //pp的拷贝构造调用
copy function10 //ppp的拷贝构造调用
constructor   //function函数调用

当函数的返回值是类对象,函数执行完成返回调用者时使用。理由也是要建立一个临时对象中,再返回调用者。

代码语言:javascript复制
#include"copy.h"

person function3(const person& p)
{
    return p;
}

int main()
{
    person p(10,20);
    function3(p);
    return 0;
}

结果:

代码语言:javascript复制
[bsk@localhost structor]$ ./a.out 
person constructor  //p的默认构造
copy function10   //function 在返回类对象时调用的拷贝构造

为什么不直接用要返回的局部对象呢?因为局部对象在离开建立它的函数时就消亡了,不可能在返回调用函数后维续生存,所以在处理这种情况时,编译系统会在调用函数的表达式中创建一个无名临时对象,该临时对象的生存周期只在函数调用处的表达式中。如果用一个新变量来接收临时对象, 临时对象变成有名对象,则此对象就不会马上销毁

所谐return对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象。如果返回的是变量,处理过程类似,只是不调用构造函数

代码语言:javascript复制
#include"copy.h"

const person& function3(const person& p)
{
    return p;
}

int main()
{
    person p(10,20);
  
  person  pp = function3(p);
  const person & ppp= function(p);//因为引用,共用一块内存空间,不会调用拷贝构造函数
    return 0;
}

结果:

代码语言:javascript复制
[bsk@localhost structor]$ ./a.out 
person constructor  //p的默认构造
copy function10   //  pp = function3(p);拷贝构造

深浅拷贝

深拷贝指的是在进行对象复制时,不仅复制了对象本身,还复制了对象所引用的其他对象,以确保复制后的对象与原始对象完全独立,彼此之间不会相互影响。换句话说,深拷贝会递归地复制对象及其所有引用的对象,从而创建一份全新的、独立的副本。

举个例子,假设有一个包含其他对象引用的复杂对象A,通过深拷贝后得到的副本B将会包含与A中相同类型和值的所有对象,而不是简单地复制它们的引用。这意味着对副本B的任何修改都不会影响原始对象A,因为它们引用的是完全独立的对象。

在编程中,实现深拷贝通常需要递归遍历对象结构,并对其中的每个对象进行复制。对于复杂的数据结构,如嵌套的列表、字典或自定义对象,确保进行深拷贝尤为重要。

深拷贝能够确保对象复制的完整性和独立性,但也需要额外的系统资源来完成复制操作。因此,在进行对象复制时,需要权衡资源消耗和需求,选择适合的复制方式。

代码语言:javascript复制
#include<iostream>
using namespace std;
class person
{
public:
	person()
	{
		cout << "person()的默认构造" << endl;
	}
	person(int age,int hight)
	{
		myage = age;
		myheight =new int( hight);
		cout << "person()的有参函数构造" << endl;
	}
	//shenkaobei
	person(const person& p)
	{
		myage = p.myage;
		//myheight = p.myheight;编译器默认(浅拷贝)提供的
		//因为是指针地址,会导致两个名释放同一块内存空间
		//深拷贝
		myheight = new int(*p.myheight);
	}
	~person()
	{
		//析构函数将,堆区 ,开辟的数据进行释放
		if (myheight != NULL)
		{
			delete myheight;
			myheight = NULL;
		}
		cout << "person()的析构函数构造" << endl;
	}
	int myage;
	int* myheight;
};
void test01()
{
	person p1(10,120);


	person p2(p1);
	cout << p2.myage<<endl <<*p2.myheight<< endl;
	return;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

0 人点赞