C++中浅拷贝、深拷贝、对象的复制、对象的赋值

一、概念字面理解

1、浅拷贝:发生对象复制时,只是对对像张数据成员进行简单的赋值。涉及到动态分配问题,如果按浅拷贝进行复制,不做特殊处理,复制完成后,两个对象中涉及动态分配空间的变量,不管他们各自的空间,及空间中的内容都是完全一样的,当对这两个对象进行析构时,会发生同一片空间被释放两次,因而会出现错误。

如指针,浅拷贝只是对指针进行复制,复制完成后,两个指针指向同一个内存空间,而深拷贝不止对指针进行复制,也对指针指向的内容进行复制,深拷贝后,两个指针指向不同地址的内存空间,但内容相同。

浅拷贝可能存在的问题(均是指存在动态分配或者指针变量的情况下):

(1)析构时,同一个内存空间可能会被释放两次,这是错误的;

(2)经浅拷贝后,指向同一个内存空间,任何一方变动都会影响到另一方;

(3)假如类存在char *ch,class_name obj1(obj),因为obj.ch和obj1.ch指向同一个内存空间,当delete obj.ch,delete.obj.ch内存被释放后,obj1.ch所指的空间不能在被利用了,delete.obj1.ch也不会成功,也会导致一直无法操作该空间,因而会导致内存泄漏结论:在释放时,会因为obj1.ch的内存没有被释放,造成内存泄漏。

eg:

  1. class Rect  
  2. {  
  3. public:  
  4. Rect() // 构造函数,p指向堆中分配的一空间  
  5. {  
  6. p = new int(100);  
  7. }  
  8. ~Rect() // 析构函数,释放动态分配的空间  
  9. {  
  10. if(p != NULL)  
  11. {  
  12. delete p;  
  13. }  
  14. }  
  15. private:  
  16. int width;  
  17. int height;  
  18. int *p; // 一指针成员  
  19. };  
  20. int main()  
  21. {  
  22. Rect rect1;  
  23. Rect rect2(rect1); // 复制对象  
  24. return 0;  
  25. }

说明:类Rect中有动态分配存在;

rect1复制给rect2,在Line23会隐式调用默认拷贝构造函数,浅拷贝,只是对象数据成员的赋值操作,此时,rect1.p和rect2.p不仅值相同,而且指向同一片空间,因此在程序执行完成前,及在进行析构时会发生错误:同一片地址空间被释放两次;

改进方法是采用深拷贝:

eg:

  1. class Rect  
  2. {  
  3. public:  
  4. Rect() // 构造函数,p指向堆中分配的一空间  
  5. {  
  6. p = new int(100);  
  7. }  
  8. Rect(const Rect& r)  
  9. {  
  10. width = r.width;  
  11. height = r.height;  
  12. p = new int; // 为新对象重新动态分配空间  
  13. *p = *(r.p);  
  14. }  
  15. ~Rect() // 析构函数,释放动态分配的空间  
  16. {  
  17. if(p != NULL)  
  18. {  
  19. delete p;  
  20. }  
  21. }  
  22. private:  
  23. int width;  
  24. int height;  
  25. int *p; // 一指针成员  
  26. };
说明:此时rect1.p和rect2.p指向不同地址空间,但他们的值是相同的。


2、深拷贝



3、对象复制


4、对象的赋值


5、默认拷贝构造函数、自定义拷贝构造函数


其他:

(1)声明一个私有的拷贝构造函数,可以防止默认拷贝发生。如果试图调用  b(a); 就调用了私有的拷贝构造函数,编译器会报错。

(2)一个类中可以存在多个拷贝构造函数。(const拷贝和非const拷贝

eg:

  1. Calss A  
  2. {  
  3. Public:  
  4. X(const X&);//const拷贝构造  
  5. X(X &);//非const拷贝构造  
  6. X(X& , int  iData);  
  7. }  

展开阅读全文

没有更多推荐了,返回首页