拷贝构造函数

  1. 何时被调用
    1. 对象间”复制“:一个对象需要另一个对象进行初始化。
      CExemple A(848);//”CExemple“是一种类,A(848)是实例化“CExemple"并调用构造函数对自身初始化
      CExemple B = A;//B用A进行初始化,在拷贝构造函数里B内变量获得和A内变量一样的值。
      //CExemple B(A);//换了个形式,其实和上一行一样。
      
    2. 对象作为值传递给函数(本质上,还是第一种)
      CExemple A;
      test(A);//当A传入函数内时,函数会先创建一个临时变量temp,然后用A初始化temp(类似于"CExemple temp(A);",此时拷贝构造函数被调用。注:当test()函数完成后会析构掉temp。
      
    3. 对象作为返回值
      CExemple test(){
          CExemple A(345);
          return A;//会先创建一个临时变量temp,然后进行"CExemple temp(A);",此时拷贝构造函数被调用。注:函数执行到最后,先析构A,函数完成后,才析构掉temp。
      }
      
  2. 深拷贝与浅拷贝
    1. 浅拷贝(类似于默认拷贝,只进行变量间值的复制) 但是当类内存在动态内存分配时需要删除动态内存,而简单的进行值复制时,指针也是一种变量,值复制会使两个指针获得相同的地址(指向同一块内存),因此删除动态内存时,会因为对同一块地址删除两次而报错。
    2. 深拷贝(是为了解决浅拷贝中的问题而产生的,深拷贝会会分配新的内存来解决浅拷贝中的问题)
      class A{
          public:
          int* value = new int;
          A(const A& a){
              int* value = new int;//申请新地址,解决浅拷贝问题
              *value = *(a.value);//这一步是赋值运算,不对指针本身的地址值值进行操作。
          }
      }
      
  3. 拷贝构造函数的几种形式
    1. A(const A& a);
    2. A(A& a);//一个类中允许有多个构造函数,但是当类只中有一个构造函数且为A(A& a)时,则不可以用const,或volatile对象进行拷贝初始化。
      const A a(88);
      A a1(a);//错误
      
    3. A(const A& a,int i = 9);
    4. 当类中没有自定义的拷贝构造函数时,编译器自己产生拷贝构造函数可能为A(const A& a)也可能为A(A& a),视上下文而定
  4. 如何防止浅拷贝的按值传递? 声明一个私有的拷贝构造函数,即使这个私有拷贝函数为空,也会在按值传递或按该类类型返回时报错,原因是私有函数在类外不可被访问

本文章使用limfx的vscode插件快速发布