zoukankan      html  css  js  c++  java
  • 关于c++深拷贝与浅拷贝

    首先看一段代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<malloc.h>
     4 using namespace std;
     5 
     6 class Teacher{
     7 public:
     8     Teacher(int id,char *name){
     9         m_id=id;
    10 
    11         m_name=(char*)malloc(strlen(name)+1);//由于显示析构函数中free内存空间,因而必须malloc
    12         strcpy(m_name,name);
    13     }
    14 
    15     void Print(){
    16         cout<<"id="<<m_id<<" name="<<m_name<<endl;
    17     }
    18 
    19     ~Teacher(){/*显示析构函数*/
    20         cout<<"Teacher()..."<<endl;
    21         if(m_name!=NULL){
    22             free(m_name);
    23             m_name=NULL;
    24         }
    25     }
    26 private:
    27     int m_id;
    28     char *m_name;
    29 };
    30 
    31 int main(){
    32     Teacher t1(1,"zhangsan");
    33     t1.Print();
    34 
    35     return 0;
    36 }

    浅谈析构函数特点:

    1.函数名是在类名前加上~,无参数且无返回值。

    2.一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。

    3.析构函数不能重载。每有一次构造函数的调用就会有一次析构函数的调用。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<malloc.h>
     4 using namespace std;
     5 
     6 class Teacher{
     7 public:
     8     Teacher(int id,char *name){
     9         cout<<"Teacher(int,char*)..."<<endl;
    10         m_id=id;
    11 
    12         int len=strlen(name);
    13         m_name=(char*)malloc(len+1);//由于显示析构函数中free内存空间,因而必须malloc
    14         strcpy(m_name,name);
    15     }
    16     /*默认拷贝构造函数,浅拷贝!!!*/
    17     Teacher(const Teacher& another){
    18         m_id=another.m_id;
    19         m_name=another.m_name;
    20     }
    21     void Print(){
    22         cout<<"id="<<m_id<<" name="<<m_name<<endl;
    23     }
    24 
    25     ~Teacher(){/*显示析构函数*/
    26         cout<<"Teacher()..."<<endl;
    27         if(m_name!=NULL){
    28             free(m_name);
    29             m_name=NULL;
    30         }
    31     }
    32 private:
    33     int m_id;
    34     char *m_name;
    35 };
    36 
    37 void test(){
    38     Teacher t1(1,"xiaoming");
    39     t1.Print();
    40 
    41     Teacher t2(t1);//t2的默认拷贝构造
    42     t2.Print();
    43 }
    44 
    45 int main(){
    46     test();
    47 
    48     return 0;
    49 }

    【浅拷贝】是增加了一个指针,指向原来已经存在的内存。

    而【深拷贝】是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间

    在test函数结束时,t1和t2都会走一遍析构函数,释放内存空间,t2后执行,因而先走析构函数,将name的内存空间释放掉,当t1走析构函数时,会再次进行m_name的内存空间释放,但由于这块内存空间在t2走析构函数时已经被释放掉了,所以在这里会引发段错误!!!,这也就是浅拷贝的危害。。。

    为了避免浅拷贝引发的段错误,因而我们需要进行深拷贝,重写拷贝构造函数

     1 #include<iostream>
     2 #include<cstring>
     3 #include<malloc.h>
     4 using namespace std;
     5 
     6 class Teacher{
     7 public:
     8     Teacher(int id,char *name){
     9         cout<<"Teacher(int,char*)..."<<endl;
    10         m_id=id;
    11 
    12         int len=strlen(name);
    13         m_name=(char*)malloc(len+1);//由于显示析构函数中free内存空间,因而必须malloc
    14         strcpy(m_name,name);
    15     }
    16     /*重写拷贝构造函数,深拷贝*/
    17     Teacher(const Teacher& another){
    18         m_id=another.m_id;
    19         //深拷贝//
    20         int len=strlen(another.m_name);
    21         m_name=(char*)malloc(len+1);
    22         strcpy(m_name,another.m_name);
    23     }
    24     void Print(){
    25         cout<<"id="<<m_id<<" name="<<m_name<<endl;
    26     }
    27 
    28     ~Teacher(){/*显示析构函数*/
    29         cout<<"Teacher()..."<<endl;
    30         if(m_name!=NULL){
    31             free(m_name);
    32             m_name=NULL;
    33         }
    34     }
    35 private:
    36     int m_id;
    37     char *m_name;
    38 };
    39 
    40 void test(){
    41     Teacher t1(1,"xiaoming");
    42     t1.Print();
    43 
    44     Teacher t2(t1);//t2的默认拷贝构造
    45     t2.Print();
    46 }
    47 
    48 int main(){
    49     test();
    50 
    51     return 0;
    52 }
    有些目标看似很遥远,但只要付出足够多的努力,这一切总有可能实现!
  • 相关阅读:
    SMS Error code: +CMS
    本地分支的使用
    Android模拟器上不了网的解决办法
    Ubuntu 下 java 版本的切换
    3GPP2 协议下载网站
    View.VISIBLE、INVISIBLE、GONE的区别
    android系统属性值的权限管理
    Ubuntu 10.10下挂载的window盘符无法获得可执行权限的问题
    appwidget 制作 note
    迭代器
  • 原文地址:https://www.cnblogs.com/Bravewtz/p/10333497.html
Copyright © 2011-2022 走看看