須要實現的基本功能:構造函數、拷貝構造函數、賦值函數、析構函數. (之前合稱big three, 如今叫作copy control)html
1 class String { 2 public: 3 String(const char* str = ""); 4 String(const String& rhs); 5 ~String(); 6 String& operator=(const String& rhs); 7 size_t size const(); 8 const char* c_str const(); 9 private: 10 char* data; 11 }; 12 13 /* 不簡潔版本 14 String::String(const char* str) { 15 if (str == NULL) { 16 data = new char[1]; 17 *data = '\0'; 18 } else { 19 int len = strlen(str); 20 data = new char[len + 1]; 21 strcpy(data, str); 22 } 23 } 24 */ 25 26 String::String(const char* str) { 27 data = new char[strlen(str) + 1]; 28 strcpy(data, str); 29 } 30 31 String::~String() { 32 delete[] data; 33 } 34 35 String::String(const String& rhs) { 36 data = new char[rhs.size() + 1]; 37 strcpy(data, rhs.c_str()); 38 } 39 40 // bad version 41 String& String::operator=(const String& rhs) { 42 if (this != &rhs) { 43 delete[] data; 44 data = new char[rhs.size() + 1]; 45 strcpy(data, rhs.c_str()); 46 } 47 return *this; 48 } 49 50 size_t String::size() const{ 51 return strlen(data); 52 } 53 54 const char* String::c_str const() { 55 return data; 56 }
改進版:【詳情參考ref四、劍指offer第一題】c++
上面的拷貝構造函數有個潛在隱患:String類涉及到內存分配操做,這個new操做可能會拋出異常。shell
解決方法:安全
能夠經過」copy and swap「的策略來實現。其原理很簡單:即先對打算修改的對象作出一個副本(copy),在副本上作必要的修改。若是生成副本時出現任何異常,原對象依然能保證不變。若是修改爲功,則經過不拋出任何異常的swap函數將副本和原對象進行交換(swap)。[ ref ]函數
1 String& String::operator=(const String &rhs) { 2 String tmp(rhs); 3 swap(data, tmp.data); 4 return *this; 5 }
若是把參數中的引用傳遞換成值傳遞,那就至關於自動建立出一個臨時對象來。以下是另外一種等價形式。this
1 String& String::operator=(String rhs) { 2 swap(data, rhs.data); 3 return *this; 4 }
在swap以後,至關於兩指針指向的內存區域進行了互換。當退出函數時,tmp生命週期已到,將被銷燬,可是它銷燬時釋放的是交換後的內存區域,即原來的data所指的內存區域;它原本指向的內存區域如今歸data管了,不會被釋放。spa
ref2和ref5都考慮了異常安全的問題。.net
ref:設計
1. 《高質量C/C++程序設計指南》附錄A,B (可能有錯誤)指針
2. http://coolshell.cn/articles/10478.html
3. http://noalgo.info/382.html
4. http://blog.csdn.net/worldwindjp/article/details/12967443
5. http://guochunyang.me/2014/10/17/c++-11-zhiyouzhi-yinyong--san---shiyong-c++-11-bianxie-string-lei-yiji--yichang-anquan--de--yunsuanfu/