c++拷贝构造函数与拷贝赋值操作符的问题
3775 点击·0 回帖
![]() | ![]() | |
![]() | 写了一个String的类,没有拷贝构造函数,但是有拷贝赋值操作符。 代码: 01 #include <iostream> 02 #include <cstring> 03 using namespace std; 04 05 class String 06 { 07 public: 08 String():data(0){ cout << "String()" << endl; } 09 String(const char *str):data(0) 10 { 11 int len = strlen(str); 12 data = new char[len + 1]; 13 strcpy(data, str); 14 cout << "String(char*)" << endl; 15 } 16 /× String(const String ;str):data(0) 17 { 18 if (this != ;str) 19 { 20 delete [] data; 21 data = new char[strlen(str.data) + 1]; 22 strcpy(data, str.data); 23 } 24 cout << "String(String;)" << endl; 25 } 26 ×/ 27 ~String() 28 { 29 cout << "~String()" << data << endl; 30 delete [] data; 31 } 32 33 String; operator=(const String ;str) 34 { 35 if (this != ;str) 36 { 37 delete [] data; 38 data = new char[strlen(str.data) + 1]; 39 strcpy(data, str.data); 40 } 41 cout << "=(String;)" << endl; 42 return *this; 43 } 44 45 String; operator=(const char *ch) 46 { 47 if (ch) 48 { 49 delete [] data; 50 data = new char[strlen(ch) + 1]; 51 strcpy(data, ch); 52 } 53 cout << "=String(char*)" << endl; 54 return *this; 55 } 56 void show() 57 { 58 if (data) 59 cout << data << endl; 60 else 61 cout << "data is null" << endl; 62 } 63 private: 64 char *data; 65 }; 01 int main(void) 02 { 03 String s; 04 s = "hello world!"; 05 s.show(); 06 String ss = s; 07 ss.show(); 08 09 return 0; 10 } 运行会出现:www.atcpu.com 1 String() 2 =String(char*) 3 hello world! 4 hello world! 5 ==(String;, String;) 6 ss is equal s 7 ~String()hello world! 8 ~String() 1 *** glibc detected *** ./a.out: double free or corruption (fasttop): 0x08ee2008 *** 2 ======= Backtrace: ========= 3 /lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x17b591]。。。。。。。。 这样的错误。 开始一头雾水,怎么也不应该出现这样的问题。后来发现原因在于: 1 String ss = s; 开始我以为这行代码会调用拷贝赋值操作符的函数,但是他却没有调用。因为这行代码是初始化ss,而不是赋值。他会去调用拷贝构造函数。加上拷贝构造函数问题就可以解决了。或者不加但是这样 1 //String ss = s; 2 String ss; 3 ss = s; 也可以。 初始化与赋值的问题在这样的情况下也有区别: 1 class Clazz 2 { 3 public: 4 Clazz(const stirng ;str):data(str){} // 初始化 5 // Clazz(const string ;str){data = str;} // 赋值 6 private: 7 string data; 8 }; 在初始化列表中,data会被直接初始化为str,即直接调用string的拷贝构造函数。 在赋值的情况下, 1 Clazz(const string ;str){data = str;} 会被转换成类似这样的形式: 1 Clazz(const string ;str):data(){data = str;} 即data的初始化分成两步,先调用string的默认构造函数,然后在调用一次拷贝赋值操作符。 所以如果可以,尽量将成员的初始化放在初始化列表中是一个不错的选择。 在《c++ primer》中是这样说的,一般情况下,初始化比赋值的效率要高。 | |
![]() | ![]() |