深拷贝和浅拷贝

1.浅拷贝:指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。
如果没有自定义拷贝构造函数,编译器会自动创建默认的拷贝构造函数,但编译器创建的拷贝构造函数只能执行“浅 拷贝”,将被拷贝对象的数据成员的值赋值给新创建的对象。
2.深拷贝:对于对象中的动态成员,重新动态分配空间,创建对象的各个成员。
3. 浅拷贝的问题:
浅拷贝的问题在于:若类的数据成员中含有指针成员,则新对象的指针指向的地址与被拷贝对象的指针指向的地址相同,delete该指针时会导致两次重复delete而出错。
为了说明浅拷贝的问题,可通过代码来看:

class Person
{
public:
    // 构造函数
    Person(const char * pN)
    {
        cout << "一般构造函数被调用 !\n";
        m_pName = new char[strlen(pN) + 1];
        //在堆中开辟一个内存块存放pN所指的字符串
        if (m_pName != NULL)
        {
            //如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它
            strcpy(m_pName, pN);
        }
    }
    // 系统创建的默认复制构造函数,只做位模式拷贝
    Person(Person & p)    
    { 
        //使两个字符串指针指向同一地址位置         
        m_pName = p.m_pName;         
    }
    ~Person()
    {
        cout << "析构函数被调用" << endl;
        delete m_pName;
    }
private:
    char * m_pName;
};
int main()
{
    Person man("lulan");
    Person woman(man);
    // 结果导致   man 和    woman 的指针都指向了同一个地址
    // 函数结束析构时
    // 同一个地址被delete两次
    return 0;
}   

通过执行上述代码,程序运行出错。因为,新创建的对象woman与原有的被拷贝的对象man的指针成员指向内存空间的同一个位置,当调用了对象的析构函数时,同一个指针被释放了两次,程序出错。这就是浅拷贝的出错表现。修改浅拷贝版本的拷贝构造函数,在拷贝构造函数中,另外动态分配内存空间,将原有对象的值赋给新分配的内存空间,修改后的代码如下:

class Person
{
public:
    // 构造函数
    Person(const char * pN)
    {
        cout << "一般构造函数被调用 !\n";
        m_pName = new char[strlen(pN) + 1];
        //在堆中开辟一个内存块存放pN所指的字符串
        if (m_pName != NULL)
        {
            //如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它
            strcpy(m_pName, pN);
        }
    }
    // 系统创建的默认复制构造函数,只做位模式拷贝
    Person(Person & chs)
    {
        // 用运算符new为新对象的指针数据成员分配空间
        m_pName = new char[strlen(chs.m_pName) + 1];
        if (m_pName)
        {
            // 复制内容
            strcpy(m_pName, chs.m_pName);
        }
        // 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了
    }
    ~Person()
    {
        cout << "析构函数被调用" << endl;
        delete m_pName;
    }

private:
    char * m_pName;
};

int main()
{
    Person man("lulan");
    Person woman(man);
    // 结果导致   man 和    woman 的指针都指向了同一个地址
    // 函数结束析构时
    // 同一个地址被delete两次
    return 0;
}

再次执行程序,程序运行正常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值