深复制、浅复制

 

     深复制、浅复制

 我们先看一个程序:
 
   #include<iostream>
   using namespace std;
   class Student
   {
    public:
 Student(int pid,char *pname,float s);
 Student(const Student&s1);
 void display();
 ~Student();
    private:
 int id;
 char*name;
 float score;
   };
   Student::Student(int pid,char*pname,float s)
     {
 id=pid;
 name=new char[strlen(pname)+1];
 strcpy(name,pname);
 score=s;
     }
   Student::Student(const Student&s1)
    {
 id=s1.id;
 name=new char[strlen(s1.name)+1];
 strcpy(name,s1.name);
 score=s1.score;
     }
   void Student::display()
    {
 cout<<"id:"<<id<<endl;
 cout<<"name:"<<name<<endl;
 cout<<"score:"<<score<<endl<<endl;
     }
   Student::~Student()
    {
 if(name!=NULL)
  delete []name;
     }
   int main()
    {
 Student s1(8410101,"Zhang Hua",95);
        s1.display();
 Student s2(s1);
 s2.display();
 return 0;
    }


  这个程序显示定义了复制构造函数,并定义了析构函数,而且析构函数在对象生命周期结束后释放了资源;如果不显示定义复制构造函数,编译将会出错。这是为什么呢?
 
  分析原因可知,如果不显示定义复制构造函数,在创建对象s2时,系统将调用默认复制构造函数并用对象s1对s2进行初始化,致使对象s1、对象s2中的指针变量指向同一存储空间。

  当一个对象生命周期结束而调用析构函数释放内存空间后,另一个对象中的指针变量被悬空(这个指针没有指向的空间了),从而无法正常运行。

在默认的复制构造函数中,复制的策略是逐个成员依次复制,但是,一个类可能会拥有资源(如堆内存),这时就出现了两个对象拥有一个资源的情况,当对象析构时,该资源将经历两次资源返还。但事实是只有一个资源,因此编译器就要报错了。

  浅复制:这种在用一个对象初始化另一个对象时,只复制了成员,并没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制。这是如果不存在资源矛盾,程序还是可以正常运行的。

  深复制:当一个对象创建时,分配了资源,这时必须显示定义复制构造函数。这种在用一个对象初始化另一个对象时不仅复制了成员也复制了资源的复制方式称为深复制。


  再看修改过的程序
      
#include<iostream>
using namespace std;
class Student
{
public:
 Student(int pid,char *pname,float s);
 //Student(const Student&s1);
 void display();
 //~Student();
private:
 int id;
 char*name;
 float score;
};
Student::Student(int pid,char*pname,float s)
{
 id=pid;
 name=new char[strlen(pname)+1];
 strcpy(name,pname);
 score=s;
}
/*Student::Student(const Student&s1)
{
 id=s1.id;
 name=new char[strlen(s1.name)+1];
 strcpy(name,s1.name);
 score=s1.score;
}*/
void Student::display()
{
 cout<<"id:"<<id<<endl;
 cout<<"name:"<<name<<endl;
 cout<<"score:"<<score<<endl<<endl;
}
/*Student::~Student()
{
 if(name!=NULL)
  delete []name;
}*/
int main()
{
 Student s1(8410101,"Zhang Hua",95);
    s1.display();
 Student s2(s1);
 s2.display();
 return 0;
}


  我们可以明显的看到,程序中把析构函数、复制构造函数都去掉了,也就是说在创建对象s2时,调用了系统默认的复制构造函数,两个对象同样指向了同一资源,但是这次却是可以正常编译,为什么?原因很简单,因为我们把释放资源的析构函数去掉了,而系统默认的析构函数又什么都不做,也就是说资源没有释放,自然就没错了。但是这容易造成泄漏,不建议这样做。

如果文章与不妥之处,还望指教。感激不尽。。

 

 
 

 

本文出自 “我的博客” 博客,转载请与作者联系!

你可能感兴趣的:(深复制,浅复制)