string四個函數的實現

來自:http://blog.csdn.net/bladelyer/article/details/7395368

// String的普通構造函數

    String::String(const char *str)

{

  if(str==NULL)

  {

    m_data = new char[1];

    *m_data = ‘\0’;

  }  

  else

  {

    int length = strlen(str);

    m_data = new char[length+1];

    strcpy(m_data, str);

  }

}  



// String的析構函數

    String::~String(void)

{

  delete [] m_data;

// 由於m_data是內部數據類型,也可以寫成 delete m_data;

    }

不要輕視拷貝構造函數與賦值函數
    由於並非所有的對象都會使用拷貝構造函數和賦值函數,程序員可能對這兩個函數有些輕視。請先記住以下的警告,在閱讀正文時就會多心:

u     本章開頭講過,如果不主動編寫拷貝構造函數和賦值函數,編譯器將以“位拷貝”的方式自動生成缺省的函數。倘若類中含有指針變量,那麼這兩個缺省的函數就隱含了錯誤。以類String的兩個對象a,b爲例,假設a.m_data的內容爲“hello”,b.m_data的內容爲“world”。

現將a賦給b,缺省賦值函數的“位拷貝”意味着執行b.m_data = a.m_data。這將造成三個錯誤:一是b.m_data原有的內存沒被釋放,造成內存泄露;二是b.m_data和a.m_data指向同一塊內存,a或b任何一方變動都會影響另一方;三是在對象被析構時,m_data被釋放了兩次。



u     拷貝構造函數和賦值函數非常容易混淆,常導致錯寫、錯用。拷貝構造函數是在對象被創建時調用的,而賦值函數只能被已經存在了的對象調用。以下程序中,第三個語句和第四個語句很相似,你分得清楚哪個調用了拷貝構造函數,哪個調用了賦值函數嗎?

String a(“hello”);

String b(“world”);

String c = a;   // 調用了拷貝構造函數,最好寫成 c(a);

c = b; // 調用了賦值函數

本例中第三個語句的風格較差,宜改寫成String c(a) 以區別於第四個語句。

類String的拷貝構造函數與賦值函數
  // 拷貝構造函數

  String::String(const String &other)

  {  

// 允許操作other的私有成員m_data

  int length = strlen(other.m_data);  

  m_data = new char[length+1];

  strcpy(m_data, other.m_data);

}



// 賦值函數

  String & String::operate =(const String &other)

  {  

    // (1) 檢查自賦值

    if(this == &other)

        return *this;

   

    // (2) 釋放原有的內存資源

    delete [] m_data;

   

    // (3)分配新的內存資源,並複製內容

  int length = strlen(other.m_data);  

  m_data = new char[length+1];

    strcpy(m_data, other.m_data);

   

    // (4)返回本對象的引用

    return *this;

}  

 

  類String拷貝構造函數與普通構造函數(參見9.4節)的區別是:在函數入口處無需與NULL進行比較,這是因爲“引用”不可能是NULL,而“指針”可以爲NULL。

  類String的賦值函數比構造函數複雜得多,分四步實現:

(1)第一步,檢查自賦值。你可能會認爲多此一舉,難道有人會愚蠢到寫出 a = a 這樣的自賦值語句!的確不會。但是間接的自賦值仍有可能出現,例如

 

// 內容自賦值

b = a;



c = b;



a = c;
// 地址自賦值

b = &a;



a = *b;




也許有人會說:“即使出現自賦值,我也可以不理睬,大不了化點時間讓對象複製自己而已,反正不會出錯!”

他真的說錯了。看看第二步的delete,自殺後還能複製自己嗎?所以,如果發現自賦值,應該馬上終止函數。注意不要將檢查自賦值的if語句

if(this == &other)

錯寫成爲

  if( *this == other)

(2)第二步,用delete釋放原有的內存資源。如果現在不釋放,以後就沒機會了,將造成內存泄露。

(3)第三步,分配新的內存資源,並複製字符串。注意函數strlen返回的是有效字符串長度,不包含結束符‘\0’。函數strcpy則連‘\0’一起復制。

(4)第四步,返回本對象的引用,目的是爲了實現象 a = b = c 這樣的鏈式表達。注意不要將 return *this 錯寫成 return this 。那麼能否寫成return other 呢?效果不是一樣嗎?

不可以!因爲我們不知道參數other的生命期。有可能other是個臨時對象,在賦值結束後它馬上消失,那麼return other返回的將是垃圾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章