一、概述
复制构造函数用于将一个对象复制到新对象中。它用于初始化过程中(包括按值传递函数),而不是常规的赋值过程中,类型如下:
Class_name(const Class_name &);
它接受一个指向类对象的常量引用作为参数。对于复制构造函数,需要知道两点:何时调用和有和功能。
①、如何调用
创建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。有四种方式
Person ob;
Person ob1(ob);//1
Person ob2=ob;//2
Person ob3 = Person (ob);//2
Person * ob4= new Person(ob);//3
②、默认构造函数功能
默认的复制构造函数逐个复制非静态成员(成员复制也称浅复制),复制的是成员的值。
Person ob("Tom",12,99.9);
Person ob1=ob;
二、浅拷贝
#include <iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
class Person
{
private:
char *m_name;
int m_num;
public:
Person()
{
m_name = NULL;
m_num = 0;
cout<<"无参构造"<<endl;
}
Person(char *name,int num)
{
//为m_name申请空间
m_name = (char *)calloc(1,strlen(name)+1);
if(m_name == NULL)
{
cout<<"构造失败"<<endl;
}
cout<<" 已经申请好空间"<<endl;
strcpy(m_name,name);
m_num = num;
cout<<"有参构造"<<endl;
}
~Person()
{
if(m_name != NULL)
{
cout<<"空间已被释放"<<endl;
free(m_name);
m_name = NULL;
}
cout<<"析构函数"<<endl;
}
void showPerson(void)
{
cout<<"m_name = "<<m_name<<", m_num = "<<m_num<<endl;
}
};
void test01()
{
Person ob("lucy",100);
ob.showPerson();
// 浅拷贝
Person ob1= ob;//调用系统的默认拷贝构造(单纯的值拷贝)
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
三、深拷贝
- 在上面的浅拷贝中在运行中ob会调用析构函数释放空间,浅拷贝ob1也会调用析构函数空间,导致释放两次调用两次析构函数,释放两次空间,出现多次释放同一块堆区空间。
- 使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深拷贝。
所有使用深拷贝解决浅拷贝的问题:
#include <iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
class Person
{
private:
char *m_name;
int m_num;
public:
Person()
{
m_name = NULL;
m_num = 0;
cout<<"无参构造"<<endl;
}
Person(char *name,int num)
{
//为m_name申请空间
m_name = (char *)calloc(1,strlen(name)+1);
if(m_name == NULL)
{
cout<<"构造失败"<<endl;
}
cout<<" 已经申请好空间"<<endl;
strcpy(m_name,name);
m_num = num;
cout<<"有参构造"<<endl;
}
Person(const Person &ob)//ob==>ob
{
cout<<"拷贝构造函数"<<endl;
m_name = (char *)calloc(1, strlen(ob.m_name)+1);
cout<<"空间已被申请"<<endl;
strcpy(m_name, ob.m_name);
m_num = ob.m_num;
}
~Person()
{
if(m_name != NULL)
{
cout<<"空间已被释放"<<endl;
free(m_name);
m_name = NULL;
}
cout<<"析构函数"<<endl;
}
void showPerson(void)
{
cout<<"m_name = "<<m_name<<", m_num = "<<m_num<<endl;
}
};
void test01()
{
Person ob("lucy",100);
ob.showPerson();
//通过自定义 拷贝构造函数 完成深拷贝动作
Person ob1 = ob;
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
- 如果类中的成员 指向了堆区空间 一定要记得在析构函数中 释放该空间;
- 如果用户 不实现 拷贝构造 系统就会提供默认拷贝构造;
- 默认拷贝构造 只是单纯的赋值 容易造成浅拷贝问题;
- 用户记得 要实现:无参构造(初始化数据)、有参构造(赋参数)、拷贝构造(深拷贝) 、析构函数(释放空间);