首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ String 類手寫實現:從深拷貝到寫時拷貝(COW)進階優化

     編輯:關於C++

深拷貝版本:經典實現

自行管理動態字元陣列,實現建構、複製、指派、析構、擴容、插入、追加等核心操作:

class String {
    friend std::ostream& operator<<(std::ostream& os, String& s);
public:
    String(const char* str = "") : _pstr(new char[strlen(str) + 1]), _size(strlen(str)), _capacity(_size) {
        strcpy(_pstr, str);
    }
    String(const String& s) : _pstr(new char[s._size + 1]), _size(s._size), _capacity(s._size) {
        strcpy(_pstr, s._pstr);
    }
    String& operator=(String s) { // Copy-and-swap 慣用法
        swap(*this, s);
        return *this;
    }
    ~String() { delete[] _pstr; }

    String& operator+=(const char* s) { /* 擴容並追加 */ }
    String& Insert(size_t pos, const char* str) { /* 擴容並插入 */ }
    void PushBack(char c) { /* 擴容並推入單字元 */ }
    char& operator[](size_t idx) { return _pstr[idx]; }
    const char* c_str() const { return _pstr; }
    size_t size() const { return _size; }

private:
    void CheckCapacity(size_t count) {
        if (_size + count >= _capacity) {
            size_t newCap = max(2 * _capacity, _capacity + count);
            char* tmp = new char[newCap];
            strcpy(tmp, _pstr);
            delete[] _pstr;
            _pstr = tmp;
            _capacity = newCap;
        }
    }
    char* _pstr;
    size_t _size;
    size_t _capacity;
};

關鍵點:指派運算子採用 Copy-and-swap 慣用法(傳值參數自動複製,交換內部指標,臨時物件析構釋放舊資源),強異常安全、碼簡潔。

寫時拷貝(COW)版本:共享優化

多個 String 物件共享同一字元緩衝區,引用計數放在緩衝區前 4 位元組:

class String {
    friend std::ostream& operator<<(std::ostream& os, String& s);
public:
    String(const char* str = "") {
        _str = new char[strlen(str) + 5]; // 前 4 bytes 存引用計數
        *(int*)(_str - 4) = 1;
        strcpy(_str, str);
    }
    String(const String& s) : _str(s._str) {
        ++*(int*)(_str - 4); // 增加引用計數
    }
    String& operator=(const String& s) {
        if (this != &s) {
            Release();
            _str = s._str;
            ++*(int*)(_str - 4);
        }
        return *this;
    }
    ~String() { Release(); }

    char& operator[](size_t idx) {
        // 讀取不觸發複製
        return _str[idx];
    }
    // 寫入操作需檢查引用計數 > 1 時觸發深拷貝
    void WriteCheck() {
        if (*(int*)(_str - 4) > 1) {
            --*(int*)(_str - 4);
            char* tmp = new char[strlen(_str) + 5];
            strcpy(tmp + 4, _str);
            _str = tmp + 4;
            *(int*)(_str - 4) = 1;
        }
    }
    // 所有修改操作前呼叫 WriteCheck()

private:
    void Release() {
        if (--*(int*)(_str - 4) == 0)
            delete[] (_str - 4);
    }
    char* _str; // 指向資料區(前 4 bytes 為引用計數)
};

COW 核心邏輯

  • 讀取:直接共享,無額外開銷。
  • 寫入:檢查引用計數,>1 時才深拷貝(Copy-on-Write),實現「讀共享、寫獨享」。
  • 引用計數管理:建構/複製增,析構/脫離減,歸零時釋放緩衝區。

現代視角的反思

C++11 移動語意普及後,COW 在多執行緒環境下引用計數的原子操作開銷、鎖競爭、偽共享等問題逐顯現。現代 std::string 多採用短字串優化(SSO) + 移動語意,而非 COW。手寫實現時,深拷貝 + 移動建構/指派 往往是更簡潔高效的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved