含有指针变量的类需要重写拷贝构造函数,拷贝赋值函数,析构函数

编译器自带拷贝构造(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

 

posted @ 2020-02-07 00:14  B_luePhantom  阅读(695)  评论(0编辑  收藏  举报