含有指针变量的类需要重写拷贝构造函数,拷贝赋值函数,析构函数
编译器自带拷贝构造(ctor)和拷贝赋值函数(operator =), 但是对于成员变量含有指针的类,其不能使用默认的拷贝赋值函数。因为使用默认的,会直接将指针指向的地址进行赋值 (浅拷贝,共享内存,共指一个对象),而不是分配一块内存,具有相同的数值 (深拷贝,独立,两个对象)。
浅拷贝容易造成dangling pointer。
用一个例子来展示:
1 #ifndef __MYSTRING__ 2 #define __MYSTRING__ 3 4 class String{ 5 public: 6 String(const char* cstr=0); 7 String(const String& str); // 拷贝构造 8 String& operator= (const String& str); // 拷贝赋值 9 ~String(); 10 char* get_c_str const(){ 11 return m_data; 12 } 13 private: 14 char* m_data; // 带指针成员的类:一定要注意拷贝赋值,拷贝构造,析构 15 // String的底部通过char实现,在外部表现为string 16 }; 17 18 inline String::String ( const char* cstr=0 ){ 19 if(cstr){ 20 m_data=new char[strlen(cstr)+1]; 21 strcpy(m_data,cstr); // char * strcpy ( char * destination, const char * source ); 22 } 23 else{ // 考虑cstr=0; 24 m_data=new char[1]; 25 m_data[0]='\0'; 26 } 27 } 28 29 inline String::String(const String& str){ 30 m_data=new char[strlen(str.get_c_str())+1]; 31 strcpy(m_data,str.m_data); 32 } 33 34 inline String::~String(){ 35 delete[] m_data; 36 } 37 38 inline String& String::operator=(const String& str){ 39 if(this==&str){ // self assignment :自我检验 (如果没有进行这样的处理,在自我赋值会产生严重的错误) 40 return *this; 41 } 42 // 构造函数是第一次,因此不需要删除,但是赋值需要先进行delete 43 delete[] m_data; // 先删除,重新分配一样大小! 44 m_data=new char[strlen(str.get_c_str())+1]; 45 strcpy(m_data,str.m_data); 46 return *this; // 其实不用返回*this也可以,因为已经实现了修改,但是这样有一个好处 可以实现 a=b=c; (因为返回的类型继续支持=) 47 } 48 49 // 调用形式: cout << String() ; 第一个参数为 << 左边 ,第二个参数为 << 右侧;返回ostream 可以实现 cout << a << b ; 50 ostream& operator<<(ostream& os,const String& str){ 51 os<<str.get_c_str(); 52 return os; 53 } 54 55 #endif