首页 > 代码库 > 类的浅度复制和深度复制

类的浅度复制和深度复制

现在我们定义一个类

//name.h

class name

{

    private:

        char *str;

        int len;

        static in num_name; //全局变量,不能在声明中初始化。(因为声明描述了如何分配内存,但不分配内存)。

    public:

       name();

       name(const char* s);

       name(const name& s);

       ~name();

}

 

//name.cpp

#include <cstring>

#include <iostream>

using namespace std;

int name::num_name = 0;

name::name()

{

    len = 4;

    str = new char[len+1];

    strcpy(str,"c++");

    num_name ++‘

}

name::name(const char* s)

{

     len = strlen(s);

     str = new char[len+1];

     strcpy(str, s);

     num_name ++;

}


name::~name()

{

    num_name--;

    delete [] str;

}

        我们把一个对象赋给另一个对象的时候会调用类的(默认的)隐式复制构造函数。默认的复制构造函数不说明其行为,因此它不指出创建过程,也不增加计数器的num_name的值,

但是析构函数更新了计数,并且在任何对象过期时都会被调用,而不管对象是如何被创建的。

        所以,我们应该自己显示定义复制构造函数。

name::name(const name& s) //显示复制构造函数

{

     num_name++;

............

}


下一个异常更微妙,隐式复制构造函数,是浅复制,对于指针类型相当于:对象A.str = 对象B.str,这种复制只是把B的字符串地址赋给A的字符串,这两个字符串指向同一字符串的同一地址,

对象A调用析构函数释放str,当对象B调用析构函数释放str的是已经被释放了的地址,这样会造成意想不到的错误,为了让对象都释放自己的字符串,所以要让对象都拥有自己的字符串,

我们要对字符串进行深度(deep)复制。

复制函数要这样写:

name::name(const name& s)

{

     num_name ++;

     len = s.len;

     str = new char[len+1];

     strcpy(str, s.str);

}


注意:如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深度复制。复制的另一种形式(成员复制或浅复制)只是复制指针指,

浅复制仅浅浅的复制指针信息,而不会深入“挖掘”来复制指针引用的结构。


类的浅度复制和深度复制