天天看点

面试知识点总结——深浅拷贝

  1. 区别
    • 在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一对一拷贝(逐位复制),当类中数据成员没有指针时,利用浅拷贝完全没有问题;但当数据成员中有指针时,如果采用简单的浅拷贝,那么两个类中的两个指针将会指向同一块地址,当对象快结束时,会调用两次析构器,从而导致指针悬挂现象,所以此时必须使用深拷贝
    • 简单来说,带指针用深拷贝,不带指针用浅拷贝
  2. 具体解释
    • 无指针的浅拷贝

      x ———-> x

      p ———-> p

    • 有指针的浅拷贝

      x ———–> x

      *p ———–> *p

      \ /

      ​ \ /

      ​ \ /

      ​ 内存

    • 有指针的深拷贝

      x ————> x

      *p ————> *p

      | |

      | |

      内存 内存

  3. 用代码解释深浅拷贝
    • 无指针的浅拷贝
      class A
      {
       public:
          A(int _data):data(_data){}
          A(){}
       private:
          int data;
      };
      
      int main()
      {
       A a();
       A b = a; //浅拷贝
      }
      //解释:b = a;就是浅拷贝,执行完b.data = 5;如果对象中没有其他资源(如:堆,文件,系统资源),则深浅无差。
                 
    • 有指针的浅拷贝(导致内存泄漏)
      class A
      {
       public:
          A(int _size):size(_size)
           {
               data = new int[size];
           }//给data分配size个内存
          A(){}
          ~A()
           {
               delete []data;
           }
       private:
          int *data;
          int size;
      };
      
      int main()
      {
       A a();
       A b = a;
      }
      //这里b = a会造成未定义行为,因为类A中拷贝构造器是编译器生成的,所以b=a执行的是浅拷贝。
      //这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时同一块内存将会被释放两次其结果是,有未定义的内存将会被泄漏或程序崩溃
                 
    • 有指针的深拷贝
      class A
      {
       public:
          A(int _size):size(_size)
           {
               data = new int[size];
           }//给data分配size个内存
          A(){}
          A(const A&_A):size(_A.size)
           {
               data = new int[size];
           }//深拷贝
          ~A()
           {
               delete []data;
           }
       private:
          int *data;
          int size;
      };
      
      int main()
      {
       A a();
       A b = a;
      }
                 

继续阅读