C++有关拷贝构造函数(默认/浅/深拷贝构造函数)

时间:2021-09-01 22:47:48

拷贝结构函数顾名思义就是复制对象。

先讲一下默认拷贝函数:

默认拷贝就是直接赋值,让程序调用默认拷贝结构函数。

Student p1;

Student p2 = p1//或者Student p2(p1);

 

程序开始运行时,创建p1对象,p1对象的构造函数从堆中分配空间并赋给数据成员pName,执行,p2=p1时,因为没有定义拷贝构造函数,于是就调用默认拷贝构造函数,
 
使得p2与p1完全一样,并没有新分配堆空间给p2,  p1与p2的pName都是同一个值。析构p2时,将堆中字符串清成空串,然后将堆空间返还给系统;
 
析构p1时,因为这是pName指向的是空串,所以第三行输出中显示的只是Destructing,当执行 delete pName ; 按道理系统应该报错,但在gcc中没有。

 

重点讲一下,深拷贝和浅拷贝。

这里借鉴一个前辈的例子:(前辈写的很好,大家可以看下)

https://www.cnblogs.com/raichen/p/4752025.html

#include <iostream>
#include <cstring>
class Person 
{
public :
         
    // 构造函数
    Person(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( )
    {
        delete m_pName;
    }
         
private :
    char * m_pName;
};
 
void main( )
{ 
    Person man("lujun");
    Person woman(man); 
     
    // 结果导致   man 和    woman 的指针都指向了同一个地址
     
    // 函数结束析构时
    // 同一个地址被delete两次
}
 
 
// 下面自己设计复制构造函数,实现“深拷贝”,即不让指针指向同一地址,而是重新申请一块内存给新的对象的指针数据成员
Person(Person & chs);
{
     // 用运算符new为新对象的指针数据成员分配空间
     m_pName=new char[strlen(p.m_pName)+ 1];
 
     if(m_pName)         
     {
             // 复制内容
            strcpy(m_pName ,chs.m_pName);
     }
   
    // 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了
}

因为编译不同,可能不能通过编译,但这不是重点。

 

直接利用浅拷贝,m_pName = p.m_pName,后者复制给前者,但资源(堆空间)并未复制给前者,相当于这两个都同时指向同一地址,造成或释放两次内存。

深拷贝上面例子可以看到,会给它新申请一个空间。

注意:(引用)“如果需要析构函数,则一定需要拷贝构造函数和赋值操作符。

 

什么情况使用复制构造函数:

类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:


(1)一个对象以值传递的方式传入函数体 


(2)一个对象以值传递的方式从函数返回 


(3)一个对象需要通过另外一个对象进行初始化。

同时别人推荐的读的文章:https://blog.csdn.net/fdsafwagdagadg6576/article/details/51723823

 

想要了解跟多可以了解一下这篇文章:《面向对象进价--拷贝构造函数》