string類的寫時拷貝

由於淺拷貝使多個對象共用一塊內存地址,調用析構函數時導致一塊內存被多次釋放,導致程序奔潰。

實現string類的時候通常顯示的定義拷貝構造函數和運算符重載函數。

 

由於釋放內存空間,開闢內存空間時花費時間,因此,在我們在不需要寫,只是讀的時候就可以不用新開闢內存空間,就用淺拷貝的方式創建對象,當我們需要寫的時候纔去新開闢內存空間。這種方法就是寫時拷貝。 

wKioL1bjs57gy9PsAAAHT7mcZX4786.png

在構造函數中開闢新的空間時多開闢4個字節的空間,用來存放引用計數器,記錄這快空間的引用次數。

#include<iostream>
#include<stdlib.h>
using namespace std;
class String
{
public:
     String(char *str = "")
      :_str(new char[strlen(str) + 5])
     {
          *(int *)_str = 1;
          _str += 4;
          strcpy(_str, str);
     }
     ~String()
     {
          if (_str != NULL)
          {
              _Release();
          }
     }
     String(const String& str)
     {
          _str = str._str;
          ++_GetRefCount();
     }
     String& operator=(const String& str)
     {
          if (this != &str)
          {
               _Release();
               _str = str._str;
               ++ _GetRefCount();
          }
          return *this;
     }
     char& operator[](int index)//寫時拷貝
     {
 
          if (_GetRefCount()>1)//當引用次數大於1時新開闢內存空間
          {
               --_GetRefCount();//原來得空間引用計數器減1
               char *str = new char[strlen(_str) + 5];
               strcpy(str+4, _str);
               _str = str+4;
               _GetRefCount()++;
          }
          return _str[index];
     }
     friend ostream& operator<<(ostream& output, const String& str)
     {
          output << str._str;
          return output;
     }
 
private:
     int& _GetRefCount()
     {
          return *(int *)(_str - 4);
     }
     void _Release()
     {
          if (--_GetRefCount() == 0)
          {
               delete[] (_str-4);
          }
     }
private:
     char *_str;
};

 

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