天天看点

关于c++中的拷贝构造函数(复制构造函数)

在c++中既存在默认构造函数,又存在默认拷贝构造函数(即复制构造函数,以下均以拷贝构造函数称呼);

例如以下申明一个Person类

Class CPerson
{
   private :
           int age;
           int height;
           char sex;
  public:
          CPerson (int age,int height,char sex);
          
             
}
CPerson::CPerson(int age,int height,char sex)
{
   age=age;
   height=height;
   sex=sex;
   CPerson * son;
}

   
           

以下实例化一个父亲的对象

CPerson father1(40,180,'男');//这会他还没有儿子
//此时如果要再实例化一个父亲对象father2,并且跟father1一模一样,这里就用到了拷贝构造函数。
CPerson father2(father1);
//另一种能达到上面这种拷贝效果的格式
//CPerson father2=father1;

 
           

以上这中拷贝方法的实现实际上是调用了了程序默认的拷贝构造函数

CPerson (const CPerson& p)//加const 是保证不能通过p来改变实参的数据成员

{

   age=p.age;

   height=p.height;

   sex=p.sex;

}

实际上就是利用了father1的引用(引用就是一种特殊的指针);

但是如果这时father1现在有儿子了(孩子他妈是谁并不重要);

father1.son=new CPerson(5,100,‘男’);

这会咱们依然将father1拷贝给father2,这时候就出现拷贝构造函数的两个重要概念:浅拷贝和深拷贝   ;

1.默认的拷贝构造函数是浅拷贝,形式如下:

 CPerson (const CPerson& p)//加const 是保证不能通过p来改变实参的数据成员

{

age=p.age;

height=p.height;

sex=p.sex;

   son=p.son;//这里就是浅拷贝,是址传递,father1和father2指向同一个儿子的内存地址

}

  在浅拷贝中就出现了另一个问题,既然是址传递,那么只要father1或者father2中任意一个son的数据成员改变,另一个人的son的数据成员同样改变

2. 深拷贝问题;首先你要明确深拷贝不是程序默认的,哎,你如果自己不写,那么就不会有深拷贝;

 具体代码:

CPerson (const CPerson& p)//加const 是保证不能通过p来改变实参的数据成员

{

age=p.age;

height=p.height;

sex=p.sex;

son=new CPerson(p.son->age,p.son->height,p.son->sex);//这里就是深拷贝,是值传递,father1和father2现在有相同特征的son.但是他们的son是各自的son,自己的son在内存上有自己的地址               }    

    关于深拷贝,这里就出现了不同于浅拷贝的地方;因为深拷贝之后的两个father有各自自己的son,只是两个son长得一模一样罢了;这时如果你改变任意一个father的son的数据成员,另一个son是不会受到影响的;

注意:浅拷贝一般不要自己写函数。深拷贝一般就要自己动手了。

另一个用到拷贝构造函数的例子

      函数的参数为对象         CPerson fffffff(CPerson person2);

        这种情况下就又会用到拷贝复制函数;

        首先调用函数时fffffff(person1);

        这是在我们看不见的程序内部到底发生了什么的?

        首先实参person1将要复制给person2(这时候就调用的拷贝构造函数),你要知道你利用了拷贝构造函数实例话一个对象后,在这个对象失效时,又必须调用析构函数,将其清除内存;而这个函数返回一个CPerson类,在你返回时,你看不见之下程序又一次调用拷贝构造函数,一来一去,两次拷贝,一次析构;      函数的多次调用对我们程序性能是不好的,会让程序运行缓慢,那么解决的办法的?

       将 CPerson fffffff(CPerson& person2);或者CPerson fffffff(CPerson* person2);

      对应的函数调用形式为 fffffff( person1);和 fffffff(&person1);

   这会咱们就是址传递了,管你呢?反正指向的同一个地址,就不存在多次调用拷贝构造函数和析构函数的问题了;

对了,处于一种好的习惯 如果你不打算改变实参的话,那么就要引用,声明函数时 CPerson fffffff(const  CPerson& person2)如果你打算改变实参就用指针,CPerson ffffff(CPerson *person2);

以上均为个人学习认识,若有知识点上和书写上的错误,欢迎各位大佬指出;

 介于CSDN新手,,,不会排版,各位大佬见谅。

继续阅读