标签:
拷贝构造函数(复制构造函数),一种特殊的构造函数,由编译器调用完成一些基于同一类的其他对象的构建及初始化。其唯一形参必须是引用,但不限制为const,一般会加上const限制。
调用拷贝构造函数情形:
事实上,拷贝构造函数是由普通构造函数和赋值操作符共同实现的。
通常,
1 class A 2 { 3 int i; 4 public: 5 A(int x):i(x){}; //构造函数 6 A(const A& b) //拷贝构造函数 7 { 8 i=b.i; 9 } 10 void show() 11 { 12 cout<<i<<endl; 13 } 14 }; 15 int main() 16 { 17 A a(100); 18 A b=a; 19 b.show(); 20 return 0; 21 }
结果为:100
可见,拷贝构造函数是一种特殊构造函数,函数名必须和类名一致,唯一的一个参数为类的引用。
1. 对象以传值的方式传入函数参数
class CExample { private: int a; public: //构造函数 CExample(int b) { a = b; cout<<"creat: "<<a<<endl; } //拷贝构造 CExample(const CExample& C) { a = C.a; cout<<"copy"<<endl; } //析构函数 ~CExample() { cout<< "delete: "<<a<<endl; } void Show () { cout<<a<<endl; } }; //全局函数,传入的是对象 void g_Fun(CExample C) { cout<<"test"<<endl; } int main() { CExample test(1); //传入对象 g_Fun(test); return 0; }
结果:
creat:1
copy
test
delete:1
delete:1
调用机制:
test对象传入形参时,会先产生一个临时变量;然后调用拷贝构造函数把test的值给临时变量;等g_fun()执行完后,析构掉临时对象。
2. 对象以值传递的方式从函数返回
#include<iostream> using namespace std; class CExample { private: int a; public: //构造函数 CExample(int b) { a = b; cout << "creat" << endl; } //拷贝构造 CExample(const CExample& C) { a = C.a; cout << "copy" << endl; } void Show() { cout << a << endl; } }; //全局函数 CExample g_Fun() { CExample temp(0); return temp; } int main() { g_Fun(); return 0; }
结果:
creat
copy
调用机制:
先产生临时变量;然后调用拷贝构造函数把temp的值给临时变量;在函数执行到最后先析构temp局部变量;等g_fun()执行完后再析构临时对象。
3. 对象需要通过另外一个对象进行初始化
CExample A(100); CExample B = A; // CExample B(A);
浅拷贝和深拷贝
1、浅拷贝,只对对象中的数据成员进行简单赋值,默认拷贝构造函数执行的就是浅拷贝。
默认拷贝函数不对静态数据成员进行处理。
一旦对象存在了动态成员,浅拷贝就会出现问题。
#include<iostream> using namespace std; class Rect { public: Rect() // 构造函数,p指向堆中分配的一空间 { p = new int(100); } ~Rect() // 析构函数,释放动态分配的空间 { if (p != NULL) { delete p; } } private: int width; int height; int *p; // 一指针成员 }; int main() { Rect rect1; Rect rect2(rect1); // 复制对象 return 0; }
出现问题,运行错误。原因在于在进行对象复制时,对于动态分配的内容没有进行正确操作。在使用rect1复制rect2时,由于执行的是浅拷贝,只是将成员的值进行赋值,所以这两个指针指向了堆里的同一个空间。在销毁对象时,两个对象的析构函数将对同一个内存空间释放两次。
2、深拷贝
#include<iostream> using namespace std; class Rect { public: Rect() // 构造函数,p指向堆中分配的一空间 { p = new int(100); } Rect(const Rect& r) { width = r.width; height = r.height; p = new int; // 为新对象重新动态分配空间 *p = *(r.p); } ~Rect() // 析构函数,释放动态分配的空间 { if (p != NULL) { delete p; } } private: int width; int height; int *p; // 一指针成员 }; int main() { Rect rect1; Rect rect2(rect1); // 复制对象 return 0; }
rect1的p和rect2的p各自指向一段内存空间,但它们指向的空间具有相同的内容。
标签:
原文地址:http://www.cnblogs.com/donald1024/p/5540706.html