實現一個簡易 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
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;
}
// 否則不釋放,由其他對象管理
}
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++11 引入移動語義和 std::string 的小字符串優化 (SSO),COW 在多線程下因原子操作開銷反而變慢,標準庫多已棄用 COW。但理解 COW 機制對掌握資源管理、引用計數、Copy-and-Swap 惯用法極有幫助。