首页后端开发其他后端知识三对象的浅拷贝和深拷贝问题

三对象的浅拷贝和深拷贝问题

时间2023-04-04 13:42:02发布访客分类其他后端知识浏览968
导读:先看示例代码 点击查看代码 #include <iostream> #include<cstring> using namespace std; class Student{ public: Stu...

先看示例代码

点击查看代码
#include iostream>
    
 #includecstring>
    
using namespace std;


class Student{


public:

    Student(int _age , const char * _name)
    {
    
         
         this->
    age=_age;
    

         int len=strlen(_name)+1;
    

         char *tep=new char[len];
    

         this->
    pName=tep;
    

         strcpy(this->
    pName,_name);


    }


    ~Student(){
    
        
        delete[]this->
    pName;
    
        this->
    pName=nullptr;

       
    }


    void showStudent(){
    
        coutthis->
    pName" "this->
    ageendl;

    }
    

 private:
    int  age;
    
    char *pName;
  
}
    ;



int main(){
    

   Student s1(20,"zhangsan");
    
   s1.showStudent();
    

   Student s2=s1;
    
  
   s2.showStudent();
    

   return 1;

}
    

上面示例代码中,对象的默认拷贝方式是内存数据拷贝,如果对象占用了外部资源,那么就会出现问题了,这里的外部资源
就是在堆上申请的空间存放名字用,
s1,s2两个对象中的名字指针都是指向了同一块堆内存区域,在结束main函数的是,s2先析构,s2会析构调堆上的内存空间,
s1再析构,由于s1对象的pName 指针和s2对象的pName指针指向的是同一块堆内存区域,但是该区域内存已经被释放了,所以遇到了问题

鉴于上面的问题,我们引出了 浅拷贝,深拷贝的问题和解决方法.

Student s2=s1; 会调用拷贝构造函数(该拷贝构造函数可以是系统自动生成的,或者你自己定义一个拷贝构造函数)
系统自动生成的拷贝构造函数做的是内存数据拷贝,所以就出现了上面的问题.因此我们需要定义属于自己的拷贝构造函数

改造代码如下

点击查看代码
class Student2{


public:

    Student2(int _age , const char * _name)
    {
            
         this->
    age=_age;
    
         int len=strlen(_name)+1;
    
         char *tep=new char[len];
       
         this->
    pName=tep;
    
         strcpy(this->
    pName,_name);
    
         cout"执行构造函数"endl;

    }
    

    //自定义拷贝构造函数
    Student2(const Student2 &
_stu2){
    

        this->
    age=_stu2.age;
        
        int len =strlen(_stu2.getPName())+1;
    
        char *newPName =new char[len];
    
        this->
    pName=newPName;
    
        strcpy(this->
    pName,_stu2.getPName());
    
        cout"执行拷贝构造函数"endl;


    }


    ~Student2(){
    
        if(this->
pName!=nullptr){
    
            delete[]this->
    pName;
    
            this->
    pName=nullptr;

        }

    }


    void showStudent(){
    

        int *p=(int *)this->
    pName;
    
        coutthis->
    pName" "this->
    age" pName Heap Address ="pendl;


    }


    const char * getPName() const{
    
         return this->
    pName;

    }
    

 private:
    int  age;
    
    char *pName;
  

}
    ;





int main(){
    

   Student2 s1(20,"zhangsan");
    
   
   s1.showStudent();
    

   Student2 s2=s1;
    

   s2.showStudent();
     


   return 1;

}
    

上面的代码还存在一个问题如下,如果在main函数中是下面的代码

Student2 s1(20,"zhangsan");

Student2 s2(30,"lisi");

s2=s1;

在main函数结束的是同样会遇到问题,这个时候就引出 赋值函数,我们需要定义自己的赋值函数

在 s2=s1这一段代码其实是这样调用的
s2.operator=(s1)

在你不定义自己的赋值函数的时候,系统会帮我们生成一个赋值函数,该赋值函数的赋值方式就是内存的数值拷贝,这种方式
在Student对象,会有问题,所以我们需要向自定义拷贝构造一样,定义一个属于自己的赋值函数

代码如下

点击查看代码
class Student3{


public:

    Student3(int _age , const char * _name)
    {
            
         this->
    age=_age;
    
         int len=strlen(_name)+1;
    
         char *tep=new char[len];
       
         this->
    pName=tep;
    
         strcpy(this->
    pName,_name);
    
         cout"执行构造函数"endl;

    }
    

    //自定义拷贝构造函数
    Student3(const Student3 &
 _stu){
    

        this->
    age=_stu.age;
        
        int len =strlen(_stu.getPName())+1;
    
        char *newPName =new char[len];
    
        this->
    pName=newPName;
    
        strcpy(this->
    pName,_stu.getPName());
    
        cout"执行拷贝构造函数"endl;


    }
    

    //自定义赋值函数
    Student3 &
     operator= (const Student3 &
 _stu){
    

        //防止自赋值
        if(this==&
_stu){
    return *this;
}
    

        //注意: 需要先释放当前的堆内存空间!!
        delete []this->
    pName;
    

        this->
    age=_stu.age;
        
        int len =strlen(_stu.getPName())+1;
    
        char *newPName =new char[len];
    
        this->
    pName=newPName;
    
        strcpy(this->
    pName,_stu.getPName());
    
        cout"执行赋值函数"endl;
    
        return *this;

    }


    ~Student3(){
    
        if(this->
pName!=nullptr){
    
            delete[]this->
    pName;
    
            this->
    pName=nullptr;

        }

    }


    void showStudent(){
    

        int *p=(int *)this->
    pName;
    
        coutthis->
    pName" "this->
    age" pName Heap Address ="pendl;


    }


    const char * getPName() const{
    
         return this->
    pName;

    }
    

 private:
    int  age;
    
    char *pName;
  

}
    ;


int main(){
    

   Student3 s3(20,"zhangsan");
    
   
   s3.showStudent();
    

   Student3 s4(30,"lisi");
    

   s4=s3;
    
   
   s4.showStudent();
    

   return 1;

}
    

运用深拷贝浅拷贝实现String 代码如下

点击查看代码
#include iostream>
    
#include cstring>
    
using namespace std;


class MyString{


public:

     //构造函数
     MyString(const char * src){


        //创建空串
        if(src==nullptr){
    
            this->
    pchar=new char[1];
    
            this->
    pchar[0]='\0';

        }

        else{
    
            int len =strlen(src)+1;
    
            this->
    pchar=new char[len];
    
            strcpy(this->
    pchar,src);

        }
    
        cout"执行构造函数, 堆内存空间地址"(int *)this->
    pchar endl;


     }
    

     //拷贝构造
     MyString(const MyString &
 myString){
    
      
        //重新分配内存空间 
        int len =myString.stringLen()+1;
    
        this->
    pchar=new char[len];
    
        strcpy(this->
    pchar,myString.pchar);
      
        cout"执行拷贝构造函数, 新创建堆内存空间地址"(int *)this->
    pchar endl;

 
     }
    

     //赋值函数
     MyString &
     operator=(const MyString &
 myString){
    

         //防止自赋值
         if(this==&
myString){
    return *this;
}
    
         //释放现有的堆内存空间
         delete[]this->
    pchar;
    
         this->
    pchar=nullptr;
    

        int len =myString.stringLen()+1;
    

        this->
    pchar=new char[len];
    
        strcpy(this->
    pchar,myString.pchar);
    
        
        cout"执行赋值函数, 新创建堆内存空间地址"(int *)this->
    pchar endl;
    

        return *this;


     }


     int stringLen() const {
         
         return strlen(this->
    pchar);

     }

    
     //析构
     ~MyString(){
    
         delete [] this->
    pchar;
    
         this->
    pchar=nullptr;

     }


     void printChar() const{
          
         coutthis->
    pcharendl;

     }
    

private:
    char *pchar;

   

}
    ;



int main(){
    

    MyString s1("abcd");
    
    s1.printChar();
    

    MyString s2=s1;
    //执行拷贝构造
    s2.printChar();
    

    MyString s3("1234");
    
    s3=s1;
    //执行赋值函数
    s3.printChar();
    

    
    return 1;

}
    

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: 三对象的浅拷贝和深拷贝问题
本文地址: https://pptw.com/jishu/1064.html
go语言从哪里开始学 go语言快速入门 php数据可视化相关内容 php能做数据分析图

游客 回复需填写必要信息