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

C++ String 類手寫實現:引用計數 + COW (Copy-On-Write) 優化

     編輯:關於C++

設計目標

實現一個簡易 String 類,支持:

  • 構造/拷貝/賦值/析構
  • += 拼接
  • ==/!= 比較
  • 流輸入輸出 >>/<<
  • 引用計數 + 寫時複製 (COW):多個 String 共享同一字符緩衝區,修改時才復制,提升拷貝/賦值效率。

核心數據結構


class Count {           // 引用計數器
    int count;
public:
    Count(): count(1) {}
    void add() { count++; }
    void dec() { count--; }
    int get() const { return count; }
};

class String {
    char* ptr;          // 字符緩衝區指針
    Count ref;          // 引用計數
    // ...
};

關鍵函數實現

構造函數


String(const char* s = "") { copy(ptr, s); }
String(const String& s) { copy(ptr, s.ptr); ref.add(); } // 共享緩衝區,計數+1

賦值運算符(Copy-and-Swap 惯用法)


String& operator=(const String& s) {
    if (this != &s) {
        String tmp(s.ptr);      // 創建臨時對象,共享 s 的緩衝區
        char* old = ptr;        // 保存舊指針
        ptr = tmp.ptr;          // 接管新緩衝區
        tmp.ptr = old;          // 臨時對象持有舊指針
        // tmp 析構時釋放舊緩衝區(若計數歸零)
    }
    return *this;
}

此寫法異常安全、自動處理自賦值、碼簡潔。

析構函數


~String() {
    if (ref.get() == 1) {       // 最後一個引用
        cout << ptr << " :del\n";
        delete[] ptr;
    }
    // 否則不釋放,由其他對象管理
}

寫時複製 (COW) 在 += 中的體現


String& operator+=(const String& s) {
    char* buf = new char[strlen(ptr) + strlen(s.ptr) + 1];
    strcpy(buf, ptr);
    strcat(buf, s.ptr);
    copy(ptr, buf);             // 重新分配,引用計數重置為 1
    return *this;
}

拼接必然修改內容,故直接新建緩衝區,不再共享。

完整代碼


#pragma once
#include 
#include 
using namespace std;

class Count {
    int count;
public:
    Count(): count(1) {}
    void add() { count++; }
    void dec() { count--; }
    int get() const { return count; }
};

class String {
    char* ptr;
    Count ref;
    void copy(char*& p, const char* s) {
        p = new char[strlen(s) + 1];
        strcpy(p, s);
    }
public:
    String(const char* s = "") { copy(ptr, s); }
    String(const String& s) { copy(ptr, s.ptr); ref.add(); }
    String& operator=(const String& s) {
        if (this != &s) {
            String tmp(s.ptr);
            char* old = ptr;
            ptr = tmp.ptr;
            tmp.ptr = old;
        }
        return *this;
    }
    ~String() {
        if (ref.get() == 1) {
            cout << ptr << " :del\n";
            delete[] ptr;
        }
    }
    friend ostream& operator<<(ostream& os, const String& s) {
        return os << s.ptr;
    }
    friend istream& operator>>(istream& is, String& s) {
        char buf[100];
        is >> buf;
        s.copy(s.ptr, buf);
        return is;
    }
    String& operator+=(const String& s) {
        char* buf = new char[strlen(ptr) + strlen(s.ptr) + 1];
        strcpy(buf, ptr);
        strcat(buf, s.ptr);
        copy(ptr, buf);
        return *this;
    }
    String& operator+=(const char* s) {
        char* buf = new char[strlen(ptr) + strlen(s) + 1];
        strcpy(buf, ptr);
        strcat(buf, s);
        copy(ptr, buf);
        return *this;
    }
    bool operator==(const String& s) const { return strcmp(ptr, s.ptr) == 0; }
    bool operator!=(const String& s) const { return strcmp(ptr, s.ptr) != 0; }
};

測試主程序


#include "String.h"
int main() {
    String s("123");
    String s1("456");
    s += s1;        // 輸出 "123 :del" 然後 "123456"
    cout << s;      // 123456
    return 0;
}

現代 C++ 注記

C++11 引入移動語義和 std::string 的小字符串優化 (SSO),COW 在多線程下因原子操作開銷反而變慢,標準庫多已棄用 COW。但理解 COW 機制對掌握資源管理、引用計數、Copy-and-Swap 惯用法極有幫助。

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