自行管理動態字元陣列,實現建構、複製、指派、析構、擴容、插入、追加等核心操作:
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 慣用法(傳值參數自動複製,交換內部指標,臨時物件析構釋放舊資源),強異常安全、碼簡潔。
多個 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 為引用計數)
};
C++11 移動語意普及後,COW 在多執行緒環境下引用計數的原子操作開銷、鎖競爭、偽共享等問題逐顯現。現代 std::string 多採用短字串優化(SSO) + 移動語意,而非 COW。手寫實現時,深拷貝 + 移動建構/指派 往往是更簡潔高效的選擇。