主要探索浅拷贝和深拷贝:
拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量。
当出现类的等号赋值时,会调用拷贝函数 在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。 但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。 所以,这时,必须采用深拷贝。 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。 简而言之,当数据成员中有指针时,必须要用深拷贝
示例一:没有指针的浅拷贝:
#include <iostream>
using namespace std;
class CExample
{
private:
int _num;
public:
CExample(int b):_num(b){}
/*
CExample(CExample other){
a=other.a;
}
*/
void set(int value){
this->_num=value;
}
void Show(){
cout<<_num<<endl;
}
};
int main()
{
CExample A(100);
CExample B=A;
B.Show();
A.set(200);
//A.Show();
B.Show();
return 0;
}
运行结果: 表明没有指针不会浅拷贝的可行性
实例二:带有指针的浅拷贝
#include <iostream>
using namespace std;
class CExample
{
private:
int _num;
char * _str;
public:
//普通构造函数
CExample(int b,char *str):_num(b){
_str=new char[b];
strcpy(_str,str);
}
/*
//拷贝构造函数
CExample(const CExample & C){
_num=C._num;
_str=new char[_num];
if(_str!=0){
strcpy(_str,C._str);
}
}
*/
~CExample(){
delete _str;
}
/*
CExample(CExample other){
a=other.a;
}
*/
void Show(){
cout<<_num<<" "<<_str<<endl;
}
};
int main()
{
CExample A(10,"hello");
CExample B=A;
B.Show();
A.Show();
A.~CExample();
A.Show();
//A.Show();
B.Show();
return 0;
}
运行结果:此时A B对象指向同一个地址,调用两次析构函数,会有野指针产生
示例三:通过深拷贝
#include <iostream>
using namespace std;
class CExample
{
private:
int _num;
char * _str;
public:
//普通构造函数
CExample(int b,char *str):_num(b){
_str=new char[b];
strcpy(_str,str);
}
//拷贝构造函数
CExample(const CExample & C){
_num=C._num;
_str=new char[_num];
if(_str!=0){
strcpy(_str,C._str);
}
}
~CExample(){
delete _str;
}
/*
CExample(CExample other){
a=other.a;
}
*/
void Show(){
cout<<_num<<" "<<_str<<endl;
}
};
int main()
{
CExample A(10,"hello");
CExample B=A;
A.Show();
//A.Show();
B.Show();
return 0;
}
运行结果:没有野指针的产生