复制构造函数——深复制 浅复制

隐含的复制构造函数并不总是适用的,因为它完成的只是浅复制。

对象的浅复制

 1 #include<iostream>
 2 #include<cassert>
 3 using namespace std;
 4 class Point{
 5 public:
 6     Point() :x(0), y(0)//默认构造函数
 7     {
 8         cout << "constructor1" << endl;
 9     }
10     Point(int x, int y) :x(x), y(y)
11     {
12         cout << "constructor2" << endl;
13     }
14     ~Point()
15     {
16         cout << "destructor" << endl;
17     }
18     int getX()
19     {
20         return x;
21     }
22     int getY()
23     {
24         return y;
25     }
26     void move(int mx, int my)
27     {
28         x += mx;
29         y += my;
30     }
31 private:
32     int x, y;
33 };
34
35 class PointArray{
36 public:
37     PointArray(int size) :size(size)
38     {
39         ptr = new Point[size];
40     }
41
42     ~PointArray()
43     {
44         cout << "析构" << endl;
45         delete[] ptr;
46     }
47
48     Point &getElement(int index)
49     {
50         assert(index >= 0 && index < size);//如果数组下标越界,程序终止
51         return ptr[index];
52     }
53
54 private:
55     Point *ptr;
56     int size;
57 };
58
59 int main()
60 {
61     int size;
62     cout << "请输入size的值:";
63     cin >> size;
64
65     PointArray pointArray1(size);
66     pointArray1.getElement(0).move(1, 1);
67     pointArray1.getElement(1).move(3, 3);
68
69     PointArray pointArray2 = pointArray1;
70     cout << pointArray2.getElement(0).getX() << "," << pointArray2.getElement(0).getY() << endl;
71     cout << pointArray2.getElement(1).getX() << "," << pointArray2.getElement(1).getY() << endl;
72
73     pointArray1.getElement(0).move(7, 7);
74     pointArray1.getElement(1).move(11, 11);
75     cout << pointArray2.getElement(0).getX() << "," << pointArray2.getElement(0).getY() << endl;
76     cout << pointArray2.getElement(1).getX() << "," << pointArray2.getElement(1).getY() << endl;
77
78     return 0;
79 }

pointArray1和pointArray2的成员ptr指向的是同一内存地址,表面上好像完成了复制,但是并没有形成真正的副本。因此当程序移动pointArray1中的点时,也影响到了pointArray2。这种效果就是浅复制。

浅复制还有更大的弊病:程序结束前,pointArray1和pointArray2的析构函数会自动被调用,动态内存空间会被释放。由于两个对象共用同一块内存空间,因此该空间被两次释放,于是导致运行错误。

对象的深复制

 1 #include<iostream>
 2 #include<cassert>
 3 using namespace std;
 4
 5 class Point{
 6 public:
 7     Point() :x(0), y(0)//默认构造函数
 8     {
 9         cout << "constructor1" << endl;
10     }
11     Point(int x, int y) :x(x), y(y)
12     {
13         cout << "constructor2" << endl;
14     }
15     ~Point()
16     {
17         cout << "destructor" << endl;
18     }
19     int getX()
20     {
21         return x;
22     }
23     int getY()
24     {
25         return y;
26     }
27     void move(int mx, int my)
28     {
29         x += mx;
30         y += my;
31     }
32 private:
33     int x, y;
34 };
35
36 class PointArray{
37 public:
38     PointArray(int size) :size(size)
39     {
40         ptr = new Point[size];
41     }
42
43     PointArray(const PointArray &pArray)
44     {
45         size = pArray.size;
46         ptr = new Point[size];
47         for (int i = 0; i < size; i++)
48         {
49             ptr[i] = pArray.ptr[i];
50         }
51     }
52
53     ~PointArray()
54     {
55         cout << "析构" << endl;
56         delete[] ptr;
57     }
58
59     Point &getElement(int index)
60     {
61         assert(index >= 0 && index < size);//如果数组下标越界,程序终止
62         return ptr[index];
63     }
64
65 private:
66     Point *ptr;
67     int size;
68 };
69
70 int main()
71 {
72     int size;
73     cout << "请输入size的值:";
74     cin >> size;
75
76     PointArray pointArray1(size);
77     pointArray1.getElement(0).move(1, 1);
78     pointArray1.getElement(1).move(3, 3);
79
80     PointArray pointArray2 = pointArray1;
81     cout << pointArray2.getElement(0).getX() << "," << pointArray2.getElement(0).getY() << endl;
82     cout << pointArray2.getElement(1).getX() << "," << pointArray2.getElement(1).getY() << endl;
83
84     pointArray1.getElement(0).move(7, 7);
85     pointArray1.getElement(1).move(11, 11);
86     cout << pointArray2.getElement(0).getX() << "," << pointArray2.getElement(0).getY() << endl;
87     cout << pointArray2.getElement(1).getX() << "," << pointArray2.getElement(1).getY() << endl;
88
89     return 0;
90 }

  移动pointArray1中的点不再影响pointArray2中的点,而且程序结束前分别释放内存空间。

时间: 2024-10-28 22:45:01

复制构造函数——深复制 浅复制的相关文章

【C/C++学院】(6)构造函数/析构函数/拷贝构造函数/深copy浅copy

1.构造函数 类的初始化即为构造函数.也为:隐式的初始化. 构造函数在对象初始化的时候,自动被调用.隐式的调用. 构造函数分为三种:有参构造函数.无参构造函数.拷贝构造函数. 有参构造函数调用有三种:括号法.等号法.手工法. #include <iostream> using namespace std; class Test { private: int m_a; public: Test()//无参构造函数 { } Test(const Test &obj)//拷贝构造函数 { }

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

一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和char *str两个成员变量, 当深复制时,A中的指针str与B中的指针str指向不同的地址,只是地址所指向的数据相同. 当浅复制时,A中的指针str与B中的指针str指向相同的地址. 1.浅复制:如果我们自己不实现复制构造函数,则C++会自动合成一个复制构造函数,又称为浅复制构造函数. 2.深复制:如果使用指针或者系统资源(如数据库

【C/C++】复制构造函数、深复制浅复制

常见问题 Q1. 下面代码的输出结果是( )? 1 #include <iostream> 2 using namespace std; 3 4 class MyClass 5 { 6 public: 7 MyClass(int n) { number = n; } 8 MyClass(const MyClass &other) 9 { 10 number = other.number; 11 cout << "a "; 12 } 13 private:

原型模式——浅复制与深复制

原型模式涉及一个浅复制和深复制的概念.原型模式可以简单理解为“复制”,但这个复制不是代码的复制.对同一个类,我们可以实例化new三次来“复制”,但如果在初始化的时候构造函数的执行很长,多次实例化就显得效率很低效了.那我们能否只实例化一次,然后“复制”呢? Test test1 = new Test(); Test test2 = test1; Test test3 = test1; 这样写吗?注意这是引用的复制,这实际上还是只有test1一个实例,test2.test3只是复制了其引用而已,如果

iOS 集合的深复制与浅复制

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

深复制与浅复制

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

关于深复制与浅复制

转自“红黑联盟”,网址:http://www.2cto.com/kf/201405/302273.html 第一.复制对象的基本概念 复制一个对象为副本,开辟一块新的内存来存储副本对象. 第二.如果一个对象想具备复制的功能,必须实现协议和协议 NSObject自带的常用的对象有:NSNumber.NSString.NSArray.NSDictionary.NSMutableArray.NSMutableDictionay.NSMutableString,copy产生的对象时不可变的,mutabl

JavaScript中对象的浅复制和深复制

在JavaScript中,如果要复制一个变量我们应该怎么做呢?下面这种做法是最简单的一种形式: //把a复制给b let a = 12; let b = a; 这种复制方法只能适用于基本类型,如果a是对象怎么办呢?我们先来看看上面的代码在内存中做了什么事: 声明了变量a = 12,栈内存会分配一块区域来存储,如上图所示.把a赋给b,会在栈中重新开辟一块区域来存储b,并且b的值就是a的值. 假如a是对象,内存做了什么事呢?来看下面的例子: let a = {}; let b = a; 如图所示,对

笔记十:复制构造函数、深拷贝、浅拷贝

复制构造函数 定义: 只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数成为复制构造函数.复制构造函数可用于: 1.根据另一个同类型的对象显示或隐式初始化一个对象 2.复制一个对象,将它作为实参传递给一个函数 3.从函数返回时复制一个对象 4.初始化顺序容器中的元素 5.根据元素初始化列表初始化数组元素 --以上定义来自<C++ Primer 中文版 第4版> 浅拷贝/浅复制 第一条中,若一个自定义类对象已经初始化了,并且用该类去初始化另一个同类类型的对象,假