C++学习基础七——深复制与浅复制

一、深复制与浅复制基本知识

深复制和浅复制,又称为深拷贝和浅拷贝。

深复制和浅复制的区别如下图1所示:

          图1

图1表示的是,定义一个类CDemo,包含int a和char *str两个成员变量,

当深复制时,A中的指针str与B中的指针str指向不同的地址,只是地址所指向的数据相同。

当浅复制时,A中的指针str与B中的指针str指向相同的地址。

1.浅复制:如果我们自己不实现复制构造函数,则C++会自动合成一个复制构造函数,又称为浅复制构造函数。

2.深复制:如果使用指针或者系统资源(如数据库,流对象等),则需要自己实现深复制的复制构造函数。

3.深复制与浅复制的代码区别:

 1 Demo(const Demo &other)
 2 {
 3    this->id= other.id;
 4     this->str = new char[1024];//深复制 ,该指针与 other内的指针变量指向两个不同的地址,只是数据相同
 5     strcpy(this->str,other.str);
 6 }
 7 或者
 8 Demo(const Demo &other)
 9 {
10      this->id= other.id;
11       //深复制 ,该指针与 other内的指针变量指向两个不同的地址,只是数据相同
12    this->str = other.str;
13 }
14 Demo(const Demo &other)
15 {
16      this->id= other.id;
17      strcpy(this->str,other.str);//浅复制
18 }

4.如果自定义的类中包含指针,则应该自己实现深复制的复制构造函数,赋值操作符和析构函数。

二、管理指针成员

浅复制时因为两个指针指向相同的地址,很有可能出现野指针的情况;

深复制不会出现野指针,但会出现很多相同的对象,浪费内存。

如何有效的使用指针成员呢?管理指针成员的三个方法如图2所示:

    图2

三种方式的具体区别如图3所示:

                图3

总结:智能指针其实是浅复制,只是智能指针不会产生野指针,而浅复制会产生野指针。

  1 #include <iostream>
  2
  3 using namespace std;
  4
  5 class ADemo
  6 {
  7 public:
  8     ADemo(int v, const int &p)
  9     {
 10         val = v;
 11         ptr = new int(p);
 12     }
 13     ~ADemo()
 14     {
 15         delete ptr;
 16     }
 17
 18     ADemo(const ADemo &other)
 19     {
 20         val = other.val;
 21         ptr = new int;
 22         *ptr = *other.ptr;//深复制
 23     }
 24
 25     ADemo& operator=(const ADemo &other)
 26     {
 27         val = other.val;
 28         ptr = new int;
 29         *ptr = *other.ptr;//深复制
 30         return *this;
 31     }
 32
 33     int get_ptr_val()
 34     {
 35         return *ptr;
 36     }
 37     void set_ptr(int v)
 38     {
 39         *ptr = v;
 40     }
 41 private:
 42     int val;
 43     int *ptr;
 44 };
 45
 46 class BDemo
 47 {
 48     public:
 49     BDemo(int v, const int &p)
 50     {
 51         val = v;
 52         ptr = new int(p);
 53     }
 54     ~BDemo()
 55     {
 56         delete ptr;
 57     }
 58
 59     BDemo(const BDemo &other)
 60     {
 61         val = other.val;
 62         ptr = other.ptr;//浅复制
 63     }
 64
 65     BDemo& operator=(const BDemo &rig)
 66     {
 67         val = rig.val;
 68         ptr = rig.ptr;//浅复制
 69         return *this;
 70     }
 71
 72     int get_ptr_val()
 73     {
 74         return *ptr;
 75     }
 76     void set_ptr(int v)
 77     {
 78         *ptr = v;
 79     }
 80 private:
 81     int val;
 82     int *ptr;
 83
 84 };
 85
 86 //====================智能指针start============
 87 class U_Ptr
 88 {
 89     friend class CDemo;
 90 private:
 91     int *ptr;
 92     size_t use;
 93     U_Ptr(int *p,int u)
 94     {
 95         this->ptr = p;
 96         use = u;
 97     }
 98     ~U_Ptr()
 99     {
100         delete ptr;
101     }
102 } ;
103
104 class CDemo
105 {//智能指针
106 public:
107     CDemo(const int &p,int v)
108     {
109         ptr = new U_Ptr(new int(p),1);
110         val = v;
111     }
112     ~CDemo()
113     {
114         if(--ptr->use == 0)delete ptr;
115     }
116
117     CDemo(const CDemo &other)
118     {
119         ++ptr->use;//多了一个对象使用
120         val = other.val;
121         ptr = other.ptr;//浅复制
122     }
123     CDemo& operator=(const CDemo &rig)
124     {
125         ++rig.ptr->use;
126         if(--ptr->use == 0)delete ptr;
127
128         val = rig.val;
129         ptr = rig.ptr;//浅复制
130         return *this;
131     }
132
133     void set_Ptr_val(int v)
134     {
135         *ptr->ptr = v;
136     }
137
138     int get_ptr_val()
139     {
140         return *ptr->ptr;
141     }
142 private:
143     int val;
144     U_Ptr *ptr;
145 };
146
147 void test_ShenCopy()
148 {
149     int prr = 20;
150     ADemo a(10,prr);
151     ADemo b = a;
152     cout<<"a = "<<a.get_ptr_val()<<endl;
153     cout<<"b = "<<b.get_ptr_val()<<endl;
154     cout<<"修改之后:"<<endl;
155     a.set_ptr(40);
156     cout<<"a = "<<a.get_ptr_val()<<endl;
157     cout<<"b = "<<b.get_ptr_val()<<endl;
158 }
159 void test_QianCopy()
160 {
161
162     int prr = 40;
163     BDemo a(50,prr);
164     BDemo b = a;
165     cout<<"a = "<<a.get_ptr_val()<<endl;
166     cout<<"b = "<<b.get_ptr_val()<<endl;
167     cout<<"修改之后:"<<endl;
168     b.set_ptr(80);
169     cout<<"a = "<<a.get_ptr_val()<<endl;
170     cout<<"b = "<<b.get_ptr_val()<<endl;
171 }
172
173 void test_smart()
174 {
175     int prr = 90;
176     CDemo a(100,prr);
177     CDemo b = a;
178     cout<<"a = "<<a.get_ptr_val()<<endl;
179     cout<<"b = "<<b.get_ptr_val()<<endl;
180     cout<<"修改之后:"<<endl;
181     b.set_Ptr_val(180);
182     cout<<"a = "<<a.get_ptr_val()<<endl;
183     cout<<"b = "<<b.get_ptr_val()<<endl;
184 }
185 int main()
186 {
187     cout<<"深复制:"<<endl;
188     test_ShenCopy();
189     cout<<endl<<"浅复制:"<<endl;
190     test_QianCopy();
191     cout<<endl<<"智能指针:"<<endl;
192     test_smart();
193     return 0;
194 }

时间: 2024-10-07 06:04:56

C++学习基础七——深复制与浅复制的相关文章

(知其所以然 主题2)从底层分析OC中ARC和非ARC下深复制和浅复制

今天,在坊间听到有人在争论OC中关于NSString的深浅复制,听了下,感觉很有必要来一个分析总结,让我们从底层去了解OC中深浅复制的运作机制. 所谓copy就是在原有对象的基础上产生一个副本对象,遵循最关键的两点原则: 1. 改变原对象的属性和行为不会对副本对象产生任何影响 2. 改变副本对象的属性和行为不会对原对象产生任何影响 在理解了这一层之后,我们一起来研究下deep copy 和 shallow copy,因为苹果是一个非常注重性能的公司,所以拷贝在底层实现没那么简单: 以NSStri

C#深复制和浅复制

本文在于巩固基础 我们来看看什么是深复制.浅复制: C#中对于数据的复制机制虽然简单但是容易让人误解.C#数据类型大体分为值类型(value type)与引用类型(reference type).对于值类型数据,复制的时候直接将数据复制给另外的变量,而对于引用型变量而言,复制时,其实只是复制了其引用.复制引用的方式叫浅复制,而逐一复制被复制对象的数据成员的方式称为深复制.

Java对象深复制、浅复制

我们在编码过程经常会碰到将一个对象传递给另一个对象,java中对于基本型变量采用的是值传递,而对于对象比如bean传递时采用的引用传递也就是地址传递,而很多时候对于对象传递我们也希望能够象值传递一样,使得传递之前和之后有不同的内存地址,在这种情况下我们一般采用以下两种情况. 浅复制与深复制概念 浅复制(浅克隆) :被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. 深复制(深克隆) :被复制对象

iOS 集合的深复制与浅复制

概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCopyArray = [someArray cop

深复制与浅复制

概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCopyArray = [someArray cop

OC 中 的copy 功能 深复制 和 浅复制 的 区别

系统的类要是实现copy拷贝的功能,必须先签订拷贝NSCopying的协议,然后实现对应的方法 在.h文件中得@interface Boy : NSObject 的后面需要签订拷贝NSCopying的协议 例子: 在.h文件中 @interface Boy : NSObject<NSCopying> 1. Boy类使用copy的方法 例子: Boy *boy =[Boy boyWithName:@"zhangyangyang" hobby:@"wan"]

.NET中深复制与浅复制

概述: 在.NET里面,提供对象复制的功能,前提是实现ICloneable接口.ICloneable接口中有一个Clone方法, 可以在类中覆写实现自定义的拷贝方法.对象复制的实现方法有两种:深复制和浅复制. 深复制和浅复制: 浅复制,浅复制是指源对象与复制出来的对象共用一份实体,对其中任何一个对象的改动都会影响另外一个对象.相当于复制了指针. 深复制:指源对象与复制对象互相独立,为新对象重新分配了一段内存空间,并复制源对象的内容.其中任何一个对象的改动都不会对另外一个对象造成影响. 深浅复制与

python 字典深复制和浅复制

#!/usr/bin/python# -*- coding: UTF-8 -*- import copydict1 = {'user': 'vickey', 'num': [1, 2, 3],'age':{'a':'1','b':'2'}}dict2 = dict1 # 对原始数据的任何操作都会影响该复制# 先进行数据的浅复制和深复制操作dict3 = dict1.copy() # 浅复制: 一级为引用对象,二级为拷贝:原始数据的二级目录改变了,浅复制的数据的二级目录也会改变,但一级目录不变di

clone()方法、深复制和浅复制

clone方法 Java中没有明确提供指针的概念和用法,而实质上没个new语句返回的都是一个指针的引用,只不过在大部分情况下开发人员不需要关心如何去操作这个指针而已. 在实际编程中,经常会遇到从某个已有对象A创建出另一个与A具有相同状态的对象B,并且B的修改不会影响到A的情况,例如Prototype(原型)模式中,就需要clone一个对象实例. 仅仅通过简单的复制操作显然无法达到这个目的,而Java提供了一个简单有效的clone()方法来满足这个需求. Java中所有的类默认都继承自Object