包含动态内存分配的类需要自定义拷贝构造函数和赋值构造函数。即当类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符,不要使用默认的。
 
无定义默认为浅拷贝,此时参数对象和创建对象(赋值对象)的指针成员指向同一块内存,调用二者的析构函数时第一对象调用释放内存成功,第二个对象会再次进行释放内存,此时运行时出错double free
 
故:应定义,且为深拷贝
二者区别是:
(1)拷贝构造函数生成新的类对象,而赋值运算符不能
(2)由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配要先释放掉
实例代码:
 1 #include<iostream>
 2 #include<string.h>
 3 
 4 class A
 5 {
 6     public:
 7         A()
 8         {
 9             std::cout << "constructor is called" << std::endl;
10             n = new int[10];
11             n[0] = 1;
12         }
13         // 默认拷贝构造函数 浅拷贝
14         /*A(const A &t) // 拷贝构造函数的参数一定是引用,否则会出现无限递归
15         {
16             std::cout << "copy constructor is called" << std::endl;
17             n = t.n
18         }*/
19 
20         // 拷贝构造函数 深拷贝
21         A(const A &t)
22         {
23             std::cout << "copy constructor is called" << std::endl;
24             n = new int[10];
25             memcpy(n, t.n, 10); // 通过按字节拷贝,将堆中一块内存存储到另一块内存
26         }
27         // 默认赋值运算符 浅拷贝 
28         /*A &operator=(const A &t) // 形参和返回值一定要是引用类型,否则传参和返回时都会自动调用拷贝构造函数,多两次函数调用,效率低
29         {
30             std::cout << "assign constructor is called" << std::endl;
31                 return *this;
32             if (n != NULL)
33             {
34                 delete n;
35                 n = NULL;
36             }
37             n = t.n;
38             return *this;
39         }*/
40         // 深拷贝
41         A &operator=(const A &t)
42         {
43             std::cout << "assign constructor is called" << std::endl;
44             if (this == &t)
45                 return *this;
46             if (n != NULL)
47             {
48                 delete n;
49                 n = NULL;
50             }
51             n = new int[10];
52             memcpy(n, t.n, 10); //通过按字节拷贝,将堆中一块内存存储到另一块内存
53             return *this;
54         }
55 
56         ~A()
57         {
58             std::cout << "destructor is called" << std::endl;
59             delete n;
60             n = NULL;
61         }
62 
63         void get() { std::cout << "n[0]: " << n[0] << std::endl; }
64     private:
65         int *n;
66 };
67 
68 int main(void)
69 {
70     A a;
71     A b(a);
72     A c;
73     b = a;
74     b.get();
75     c.get();
76 
77     return 0;
78 }

编译运行结果:

posted on 2015-03-06 11:09  pluser  阅读(1251)  评论(0编辑  收藏  举报