一 概述
编译器提供了默认构造函数和析构函数,同样也提供了复制构造函数,编译器提供的默认复制函数只是把传递进来的对象的每个成员变量复制到新对象的成员变量中去。然后两个对象的变量均指向存放类成员变量的那块内存区域。
二 逻辑说明
2.1 指针变量
- 假如该变量是指针变量,一般不会立即出错,假如该变量是指针变量,如图
- 现在对象a有一个指针成员变量x,它指向堆中存放6的那块内存区域,我们将对象a复制到对象b,如:A b=(a);
- 由于要复制对象,因此自动调用默认复制构造函数,调用的过程为:
- 首先将对象a作为参数传递到默认复制构造函数中,然后将对象a的指针成员变量x复制到对象b中,这样两个对象的指针x现在都指向同一内存区域。
- 这样当这两个对象中的任何一个超出作用域时,都会出现致命的错误。比如说我们将对象a删除,那么析构函数会自动释放堆中存放6的那块内存空间,而对象b的指针变量x仍指向该空间,由于该空间已经不在,那么对象b的指针变量x现在就变成了一个迷途指针,该程序面临奔溃的边缘。
三 示例及输出结果
3.1 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include<iostream> using namespace std; class A { private: int *x; public: A() { x = new int; *x = 5; } ~A() { delete x; x = NULL; } A(const A &a) { cout << "复制构造函数执行。。。。\n" << endl; x = a.x; } void print() const {cout << *x << endl;} void set(int i) {*x = i;} }; int main() { A *a = new A(); cout << "a:"; a->print(); A b = *a; cout << "b:"; b.print(); a->set(32); cout << "b:"; b.print(); //delete a; return 0; }
|
3.2 输出结果
1 2 3 4 5
| a:5 复制构造函数执行。。。。
b:5 b:32
|
3.3 代码说明
- 利用a对象复制成新对象,对象a删除后,对象b称为迷途对象,出现错误