一、拷贝构造函数的定义
定义
在一个类中,通过一个已经存在的对象初始化该类的另一个对象。在程序中,我我们经常有这样的定义变量:int a=10,然后int b=a。在类中,我们需要拷贝构造函数才能完成这样的功能。
格式
class Car{
public:
Car(const Car& another); //声明拷贝构造函数
//...
};
其中,使用const修饰对象是为了使引用的对象不被修改。
拷贝构造函数的定义与调用示例
#include<iostream>
using namespace std;
class Car {
public:
Car(string color, int id); //声明构造函数
Car(const Car& another); //声明拷贝构造函数
void message();
~Car(); //声明析构函数
private:
string _color;
int _id;
};
Car::Car(string color, int id)//类外实现构造函数
{
cout << "车辆信息" << endl;
_color = color;
_id = id;
}
Car::Car(const Car& another)//类外实现拷贝构造函数
{
cout << "车辆信息" << endl;
_color = another._color;
_id = another._id;
}
void Car::message()
{
cout << _color<<" "<<_id << endl;
}
int main()
{
Car car_a("yellow", 88888888);
car_a.message();
Car car_b(car_a); //使用对象car_a初始化对象car_b
car_b.message();
return 0;
}
二、浅拷贝
定义
默认的拷贝构造函数只能完成简单的赋值操作,不能完成含有堆内存成员数据的拷贝。
比如类中有指针类型的数据,若使用拷贝构造函数进行简单的赋值操作,只是将新对象的指针指向原有指针指向的内存空间,也就是说,拷贝后的指针并没有开辟新的内存空间,这就是浅拷贝。
浅拷贝示例
#include<iostream>
using namespace std;
class Car{
public:
Car(char* color,int id);
Car(const Car& another);
void message();
~Car();
private:
char* _color; //指针成员
int _id;
};
Car::car(char *color,int id)
{
_id=id;
//为指针color分配空间,将形参color的内容复制到_color指向的空间
int len=strlen(color)+1;
_color=new char[len];
memset(color,0,len);
strcpy(_color,color);
}
Car::Car(const Car& another){
_color=another._color;
_id=another.id;
}
void Car::show(){
cout<<_color<<_id<<endl;
}
Car::~Car() //调用析构函数,如果_color不为空,则释放空间
{
if(_color!=NULL)
delete _color;
}
int main()
{
const string *c="white";
Car car_a(p,88888888);
car_a.message();
Car car_b(car_a);
car_b.message();
return 0;
}
在上述程序中,由于对象car_a与对象car_b中的_color指针指向同一块内存空间,而析构函数却会对该内存空间释放两次,第二次释放时,该内存空间无数据,为空,因而触发断点,这种现象称为重析构。
三、深拷贝
定义
在拷贝构造函数中完成更加深层次的复制。当类中有指针时,深拷贝可以为新对象开辟一块新的内存空间,在析构时可以析构各自对象,便不会发生冲突。
Car::Car(const Car& another){
_color=another._color;
_id=another.id;
//实现深拷贝
int len=strlen(another._color)+1;
_color=new char[len];
strcpy(_color,another._color);
}
四、拓展
memset函数
格式声明
void *memset(void *str, int c, size_t n)
参数
str 指向要填充的内存块。
c 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
n 要被设置为该值的字符数。