手写C++ string类实现详解

类定义

cpp

复制代码
namespace ym {
    class string {
    private:
        char* _str;        // 字符串数据
        size_t _size;      // 当前字符串长度
        size_t _capacity;  // 当前分配的内存容量
        static const size_t npos = -1;  // 特殊值,表示最大可能位置
        
    public:
        // 构造函数和析构函数
        string(const char* str = "");
        string(const string& s);
        ~string();
        
        // 迭代器支持
        typedef char* iterator;
        typedef const char* const_iterator;
        iterator begin();
        iterator end();
        // ... 其他成员函数
    };
}

核心功能实现

1. 内存管理

reserve() 函数

cpp

复制代码
void string::reserve(size_t n) {
    if (n > _capacity) {
        char* str = new char[n + 1];  // 多分配1字节存放'\0'
        strcpy(str, _str);
        delete[] _str;
        _str = str;
        _capacity = n;
    }
}
push_back() 函数

cpp

复制代码
void string::push_back(char ch) {
    if (_size == _capacity) {
        reserve(_capacity == 0 ? 4 : 2 * _capacity);  // 初始容量为4,之后每次翻倍
    }
    _str[_size++] = ch;
    _str[_size] = '\0';  // 确保字符串始终以'\0'结尾
}

2. 字符串操作

append() 函数

cpp

复制代码
void string::append(const char* str) {
    size_t len = strlen(str);
    if (_size + len > _capacity) {
        reserve(max(_size + len, 2 * _capacity));  // 按需扩容
    }
    strcat(_str + _size, str);  // 追加字符串
    _size += len;
}
insert() 函数

cpp

复制代码
void string::insert(size_t pos, const char* str) {
    assert(pos <= _size);
    size_t len = strlen(str);
    if (_size + len > _capacity) {
        reserve(_size + len);
    }
    
    // 向后移动字符
    memmove(_str + pos + len, _str + pos, _size - pos + 1);  // +1包含'\0'
    
    // 插入新内容
    memcpy(_str + pos, str, len);
    _size += len;
}

3. 运算符重载

赋值运算符

cpp

复制代码
string& string::operator=(string s) {
    if (this != &s) {  // 防止自赋值
        delete[] _str;
        _str = new char[s._capacity + 1];
        strcpy(_str, s._str);
        _size = s._size;
        _capacity = s._capacity;
    }
    return *this;
}
比较运算符

cpp

复制代码
bool operator<(const string& s1, const string& s2) {
    return strcmp(s1.c_str(), s2.c_str()) < 0;
}
// 其他比较运算符类似...

4. 流操作符

输出运算符

cpp

复制代码
ostream& operator<<(ostream& out, const string& s) {
    for (auto ch : s) {  // 使用范围for循环
        out << ch;
    }
    return out;
}
输入运算符(优化版)

cpp

复制代码
istream& operator>>(istream& in, string& s) {
    s.clear();
    const int N = 256;  // 缓冲区大小
    char buff[N];
    int i = 0;
    char ch;
    
    // 跳过前导空白
    while (in.get(ch) && isspace(ch)) {}
    
    // 读取直到遇到空白
    if (!in.eof()) {
        do {
            buff[i++] = ch;
            if (i == N - 1) {  // 缓冲区快满时
                buff[i] = '\0';
                s += buff;
                i = 0;
            }
        } while (in.get(ch) && !isspace(ch));
        
        // 处理剩余字符
        if (i > 0) {
            buff[i] = '\0';
            s += buff;
        }
    }
    return in;
}

关键设计点

  1. 内存管理

    • 使用new[]delete[]手动管理内存

    • 采用指数级扩容策略(初始4,之后每次翻倍)

    • 始终确保字符串以'\0'结尾

  2. 异常安全

    • 赋值运算符使用拷贝交换惯用法

    • 关键操作前进行断言检查

  3. 性能优化

    • 输入操作符使用缓冲区减少扩容次数

    • 使用memmovememcpy提高大块数据操作效率

  4. 标准兼容

    • 提供迭代器支持

    • 实现完整的比较运算符

    • 支持流操作符

使用示例

cpp

复制代码
ym::string s1 = "Hello";
ym::string s2 = "World";

s1 += " ";
s1 += s2;  // s1变为"Hello World"

cout << s1 << endl;  // 输出: Hello World

ym::string s3;
cin >> s3;  // 读取输入