c++复习记录1 深拷贝与浅拷贝

一、深拷贝与浅拷贝

浅拷贝又称为引用拷贝,就是拷贝之后,共用同一个实体,只是引用名不同了,对其所做的改变都将改变原来的值。

深拷贝又称为值拷贝,拷贝之后,有不同的名字,不同的内存空间,对其所做的改变都不会改变原来的值。

主要区别:在拷贝指针的时候,浅拷贝只是把指针拷贝一份,指针所指的内容不拷贝,拷贝后的结果是,两个不同的指针,但是指向同一块内存地址,这样就造成了在调用析构函数进行析构的时候,对同一块内存会析构两次,从而造成程序崩溃,内存泄露。

                   可以举例来理解,比如原函数中自定义的构造函数中,存在通过new进行动态分配的数据成员(new返回的是一个指针,指向新分配的内存,也就是拷贝时存在指针的拷贝的情况),而如果原函数中没有自定义的拷贝构造函数(内含对动态数据成员的重新动态分配),此时系统就会调用默认的构造函数,也就是只拷贝了指针,而该拷贝后的指针仍然指向原分配的内存。

                      浅拷贝,不只是把指针拷贝一份,还拷贝指针所指向的内容,拷贝后的结果是不同的两个指针,分别指向两个不同的内存。

所以在对象中存在指针或者引用的拷贝时,存在动态成员时,存在堆(比如new这种动态分配时),文件,系统资源时,一定要用深拷贝,避免浅拷贝,而避免浅拷贝是通过,添加自定义的拷贝构造函数,并且在自定义的拷贝构造函数中必须对动态成员,重新进行内存的动态分配。

  

会调用拷贝构造函数的情况:

1 类的对象作为函数的参数进行传值时

比如: Point  A; func(A);//Point是一个类,A是这个类的对象,在此可以看出func函数的形参是一个类的引用。

2 类的对象以传值的方式作为函数的返回对象的时候

比如:Point func();

3 类的对象给类的对象赋值时

比如:Point A;  Point B=A;

以上三种情况都会调用拷贝构造函数,如果没有自定义的拷贝构造函数,系统就会调用默认的拷贝构造函数。


需要我们自定义拷贝构造函数的情况:

1当自定义的构造函数中含有对静态数据成员的处理时。

比如:类Point中的数据成员是:static int count; int a; int b;

           自定义的构造函数是:Point(){  count++;}

            则系统默认生成的拷贝构造函数:

          Point(const Point &p){  a=p.a;  b=p.b;  }//没有对count自增的拷贝处理

          此时本来输出的count为类的对象的个数,这是就不对了。

          Point A;  Point B=A;此时count本来应该输出2的,但是拷贝的时候没有自增,所以还是1;

          需要我们自己定义的拷贝构造函数是:

          Point(const Point &p){  a=p.a;  b=p.b;   count++;}

2 在存在动态成员时,避免浅拷贝,也就是当自定义的构造函数中存在动态成员时,必须自定义拷贝构造函数对动态成员进行重新动态内存分配

比如:类Point中的数据成员有:int a; int b;

          类Point中的构造函数如下:Point(){  m=new int(50);}

          Point(const Point &p){  a=p.a;  b=p.b;  *m=*(p.m);   }//没有对m重新进行内存动态分配

           需要我们自定义的拷贝构造函数是:

           Point(const Point &p){  a=p.a;  b=p.b;  m=int  new(50);   *m=*(p.m);}


如何避免对默认构造函数的调用,就是在函数中声明一个私有的拷贝构造函数,不必实现。这样以上情况发生的时候,编译就会报错提醒我们。

比如:Point(const Point &p){ }


关于构造函数的一些疑惑:

1一个函数中可以存在多个拷贝构造函数,比如一个const的一个非const的

                                                  Point(const  Point &);

                                                  Point(Point &);

2如何判断是否为拷贝构造函数:构造函数的第一个参数是该类的一个对象的引用,没有其他参数或者其他参数有默认值。

比如 

                                                  Point(Point &);

                                                  Point(Point &,int a=0);

3 拷贝构造函数可以调用类中的private成员。

                                                  

猜你喜欢

转载自blog.csdn.net/shiyuqing1207/article/details/46714267