ITPub博客

首页 > 应用开发 > IT综合 > C++ string类深度实现:从零构建与底层机制全解析

C++ string类深度实现:从零构建与底层机制全解析

投稿 IT综合 作者:bhluo 时间:2026-01-04 13:59:39 0 删除 编辑

# C++ string类深度实现:从零构建与底层机制全解析


## 引言:深入理解STL string的设计哲学


C++标准库中的string类虽然接口简洁,但其内部实现蕴含着诸多精妙的设计考量。通过亲手实现一个简易的string类,我们可以深入理解动态内存管理、RAII原则、值语义等C++核心概念。本文将从头开始构建一个完整的MyString类,剖析每个实现细节。


## 1. 基础框架设计与内存管理


### 1.1 类的基本结构


```cpp

#ifndef MYSTRING_H

#define MYSTRING_H


#include <iostream>

#include <cstring>

#include <algorithm>


class MyString {

private:

    char* m_data;      // 字符数组指针

    size_t m_length;   // 字符串长度(不含结尾的'\0')

    size_t m_capacity; // 分配的内存容量

    

    // 辅助函数:计算容量增长策略

    static constexpr size_t DEFAULT_CAPACITY = 15;  // 默认容量

    static constexpr size_t GROWTH_FACTOR = 2;      // 增长因子

    

    size_t calculate_new_capacity(size_t required) const {

        size_t new_capacity = (m_capacity == 0) ? DEFAULT_CAPACITY : m_capacity;

        while (new_capacity < required) {

            new_capacity *= GROWTH_FACTOR;

            // 防止溢出

            if (new_capacity < m_capacity) {

                new_capacity = required;

                break;

            }

        }

        return new_capacity;

    }

    

    // 重新分配内存

    void reallocate(size_t new_capacity) {

        if (new_capacity <= m_capacity) {

            return;  // 不需要重新分配

        }

        

        char* new_data = new char[new_capacity + 1];  // +1用于'\0'

        

        if (m_data != nullptr) {

            // 复制现有数据

            std::memcpy(new_data, m_data, m_length);

            delete[] m_data;  // 释放旧内存

        }

        

        m_data = new_data;

        m_capacity = new_capacity;

        m_data[m_length] = '\0';  // 确保以'\0'结尾

    }

    

public:

    // 构造函数系列

    MyString();                         // 默认构造函数

    MyString(const char* str);          // C风格字符串构造

    MyString(const MyString& other);    // 拷贝构造函数

    MyString(MyString&& other) noexcept; // 移动构造函数

    ~MyString();                        // 析构函数

    

    // 赋值运算符

    MyString& operator=(const MyString& other); // 拷贝赋值

    MyString& operator=(MyString&& other) noexcept; // 移动赋值

    MyString& operator=(const char* str);       // C字符串赋值

    

    // 访问接口

    size_t length() const noexcept { return m_length; }

    size_t capacity() const noexcept { return m_capacity; }

    bool empty() const noexcept { return m_length == 0; }

    const char* c_str() const noexcept { return m_data ? m_data : ""; }

    

    // 元素访问

    char& operator[](size_t index);

    const char& operator[](size_t index) const;

    char& at(size_t index);

    const char& at(size_t index) const;

    

    // 修改操作

    MyString& append(const MyString& str);

    MyString& append(const char* str);

    MyString& operator+=(const MyString& str);

    MyString& operator+=(const char* str);

    

    void clear() noexcept;

    void reserve(size_t new_capacity);

    void shrink_to_fit();

    

    // 比较运算符

    bool operator==(const MyString& other) const;

    bool operator!=(const MyString& other) const;

    bool operator<(const MyString& other) const;

    bool operator>(const MyString& other) const;

    bool operator<=(const MyString& other) const;

    bool operator>=(const MyString& other) const;

    

    // 查找操作

    size_t find(const MyString& str, size_t pos = 0) const noexcept;

    size_t find(const char* str, size_t pos = 0) const noexcept;

    size_t find(char ch, size_t pos = 0) const noexcept;

    

    // 子串操作

    MyString substr(size_t pos = 0, size_t count = npos) const;

    static const size_t npos = static_cast<size_t>(-1);

    

    // 流操作符

    friend std::ostream& operator<<(std::ostream& os, const MyString& str);

    friend std::istream& operator>>(std::istream& is, MyString& str);

};


#endif // MYSTRING_H

```


## 2. 构造函数与析构函数实现


### 2.1 核心构造方法


```cpp

// 默认构造函数

MyString::MyString() 

    : m_data(nullptr), m_length(0), m_capacity(0) {

    // 延迟分配内存,提高效率

}


// C风格字符串构造函数

MyString::MyString(const char* str) {

    if (str == nullptr || str[0] == '\0') {

        m_data = nullptr;

        m_length = 0;

        m_capacity = 0;

        return;

    }

    

    m_length = std::strlen(str);

    m_capacity = calculate_new_capacity(m_length);

    m_data = new char[m_capacity + 1];  // +1 for '\0'

    

    // 使用memcpy而不是strcpy,提高性能

    std::memcpy(m_data, str, m_length);

    m_data[m_length] = '\0';

}


// 拷贝构造函数(深拷贝)

MyString::MyString(const MyString& other) {

    if (other.m_data == nullptr) {

        m_data = nullptr;

        m_length = 0;

        m_capacity = 0;

        return;

    }

    

    m_length = other.m_length;

    m_capacity = other.m_capacity;

    m_data = new char[m_capacity + 1];

    

    std::memcpy(m_data, other.m_data, m_length + 1); // 包含'\0'

}


// 移动构造函数(C++11)

MyString::MyString(MyString&& other) noexcept

    : m_data(other.m_data), 

      m_length(other.m_length), 

      m_capacity(other.m_capacity) {

    // 转移资源所有权

    other.m_data = nullptr;

    other.m_length = 0;

    other.m_capacity = 0;

}


// 析构函数

MyString::~MyString() {

    clear_memory();

}


// 私有辅助函数:清理内存

void MyString::clear_memory() noexcept {

    if (m_data != nullptr) {

        delete[] m_data;

        m_data = nullptr;

    }

    m_length = 0;

    m_capacity = 0;

}

```


### 2.2 赋值运算符实现


```cpp

// 拷贝赋值运算符(copy-and-swap惯用法)

MyString& MyString::operator=(const MyString& other) {

    if (this == &other) {

        return *this;  // 处理自赋值

    }

    

    // 创建临时副本

    MyString temp(other);

    

    // 交换资源

    swap(*this, temp);

    

    return *this;

}


// 移动赋值运算符

MyString& MyString::operator=(MyString&& other) noexcept {

    if (this == &other) {

        return *this;

    }

    

    // 释放当前资源

    clear_memory();

    

    // 转移资源

    m_data = other.m_data;

    m_length = other.m_length;

    m_capacity = other.m_capacity;

    

    // 置空源对象

    other.m_data = nullptr;

    other.m_length = 0;

    other.m_capacity = 0;

    

    return *this;

}


// C字符串赋值运算符

MyString& MyString::operator=(const char* str) {

    if (str == nullptr || str[0] == '\0') {

        clear();

        return *this;

    }

    

    size_t new_length = std::strlen(str);

    

    if (new_length > m_capacity) {

        // 需要重新分配内存

        clear_memory();

        m_length = new_length;

        m_capacity = calculate_new_capacity(new_length);

        m_data = new char[m_capacity + 1];

    } else {

        // 重用现有内存

        m_length = new_length;

    }

    

    std::memcpy(m_data, str, new_length);

    m_data[m_length] = '\0';

    

    return *this;

}


// 交换函数(noexcept保证强异常安全)

void swap(MyString& a, MyString& b) noexcept {

    using std::swap;

    swap(a.m_data, b.m_data);

    swap(a.m_length, b.m_length);

    swap(a.m_capacity, b.m_capacity);

}

```


## 3. 元素访问与修改操作


### 3.1 安全访问接口


```cpp

// 下标运算符(无边界检查)

char& MyString::operator[](size_t index) {

    // 允许修改已有字符,但不能越界访问

    return m_data[index];

}


const char& MyString::operator[](size_t index) const {

    return m_data[index];

}


// at方法(有边界检查)

char& MyString::at(size_t index) {

    if (index >= m_length) {

        throw std::out_of_range("MyString::at - index out of range");

    }

    return m_data[index];

}


const char& MyString::at(size_t index) const {

    if (index >= m_length) {

        throw std::out_of_range("MyString::at - index out of range");

    }

    return m_data[index];

}


// 首尾字符访问

char& MyString::front() {

    if (empty()) {

        throw std::logic_error("MyString::front - string is empty");

    }

    return m_data[0];

}


const char& MyString::front() const {

    if (empty()) {

        throw std::logic_error("MyString::front - string is empty");

    }

    return m_data[0];

}


char& MyString::back() {

    if (empty()) {

        throw std::logic_error("MyString::back - string is empty");

    }

    return m_data[m_length - 1];

}


const char& MyString::back() const {

    if (empty()) {

        throw std::logic_error("MyString::back - string is empty");

    }

    return m_data[m_length - 1];

}

```


### 3.2 字符串修改操作


```cpp

// 追加操作

MyString& MyString::append(const MyString& str) {

    return append(str.m_data, str.m_length);

}


MyString& MyString::append(const char* str) {

    if (str == nullptr || str[0] == '\0') {

        return *this;

    }

    

    size_t append_length = std::strlen(str);

    return append(str, append_length);

}


// 私有辅助函数:带长度的追加

MyString& MyString::append(const char* str, size_t append_length) {

    if (append_length == 0) {

        return *this;

    }

    

    size_t new_length = m_length + append_length;

    

    // 检查是否需要重新分配内存

    if (new_length > m_capacity) {

        size_t new_capacity = calculate_new_capacity(new_length);

        reallocate(new_capacity);

    }

    

    // 追加新内容

    std::memcpy(m_data + m_length, str, append_length);

    m_length = new_length;

    m_data[m_length] = '\0';

    

    return *this;

}


// 运算符重载

MyString& MyString::operator+=(const MyString& str) {

    return append(str);

}


MyString& MyString::operator+=(const char* str) {

    return append(str);

}


// 插入操作

MyString& MyString::insert(size_t pos, const MyString& str) {

    if (pos > m_length) {

        throw std::out_of_range("MyString::insert - position out of range");

<"gov.g1k5.org.cn"><"pe.g1k5.org.cn"><"tz.g1k5.org.cn"><"n1.g1k5.org.cn">

    }

    

    if (str.empty()) {

        return *this;

    }

    

    size_t new_length = m_length + str.m_length;

    

    // 检查容量

    if (new_length > m_capacity) {

        size_t new_capacity = calculate_new_capacity(new_length);

        char* new_data = new char[new_capacity + 1];

        

        // 复制插入点前的部分

        std::memcpy(new_data, m_data, pos);

        

        // 复制插入的字符串

        std::memcpy(new_data + pos, str.m_data, str.m_length);

        

        // 复制插入点后的部分

        std::memcpy(new_data + pos + str.m_length, 

                   m_data + pos, 

                   m_length - pos);

        

        delete[] m_data;

        m_data = new_data;

        m_capacity = new_capacity;

    } else {

        // 在现有内存中移动数据

        // 向后移动现有数据

        std::memmove(m_data + pos + str.m_length,

                    m_data + pos,

                    m_length - pos);

        

        // 插入新数据

        std::memcpy(m_data + pos, str.m_data, str.m_length);

    }

    

    m_length = new_length;

    m_data[m_length] = '\0';

    

    return *this;

}


// 删除操作

MyString& MyString::erase(size_t pos, size_t count) {

    if (pos >= m_length) {

        throw std::out_of_range("MyString::erase - position out of range");

    }

    

    // 计算实际要删除的数量

    size_t actual_count = (count == npos || pos + count > m_length) 

                        ? m_length - pos 

                        : count;

    

    if (actual_count == 0) {

        return *this;

    }

    

    // 移动数据覆盖要删除的部分

    std::memmove(m_data + pos,

                m_data + pos + actual_count,

                m_length - pos - actual_count);

    

    m_length -= actual_count;

    m_data[m_length] = '\0';

    

    return *this;

}

```


## 4. 容量管理与内存优化


### 4.1 动态内存管理


```cpp

// 清空字符串内容

void MyString::clear() noexcept {

    if (m_data != nullptr) {

        m_data[0] = '\0';

    }

    m_length = 0;

}


// 预留容量

void MyString::reserve(size_t new_capacity) {

    if (new_capacity <= m_capacity) {

        return;

    }

    

    reallocate(new_capacity);

}


// 缩减容量以匹配大小

void MyString::shrink_to_fit() {

    if (m_capacity > m_length) {

        if (m_length == 0) {

            clear_memory();

        } else {

            size_t new_capacity = m_length;

            char* new_data = new char[new_capacity + 1];

            

            std::memcpy(new_data, m_data, m_length + 1);

            delete[] m_data;

            

            m_data = new_data;

            m_capacity = new_capacity;

        }

    }

}


// 重新分配内存实现

void MyString::reallocate(size_t new_capacity) {

    if (new_capacity <= m_capacity) {

        return;

    }

    

    char* new_data = new char[new_capacity + 1];

    

    if (m_data != nullptr) {

        // 复制现有数据

        std::memcpy(new_data, m_data, m_length);

        new_data[m_length] = '\0';

        delete[] m_data;

    } else {

        new_data[0] = '\0';

    }

    

    m_data = new_data;

    m_capacity = new_capacity;

}


// 调整大小

void MyString::resize(size_t new_length, char ch) {

    if (new_length <= m_length) {

        // 缩小字符串

        m_length = new_length;

        m_data[m_length] = '\0';

    } else {

        // 扩大字符串

        if (new_length > m_capacity) {

            reallocate(calculate_new_capacity(new_length));

        }

        

        // 填充新字符

        for (size_t i = m_length; i < new_length; ++i) {

            m_data[i] = ch;

        }

        

        m_length = new_length;

        m_data[m_length] = '\0';

    }

}

```


## 5. 字符串比较与查找算法


### 5.1 比较操作实现


```cpp

// 比较运算符

bool MyString::operator==(const MyString& other) const {

    if (this == &other) return true;

    if (m_length != other.m_length) return false;

    if (m_data == nullptr && other.m_data == nullptr) return true;

    if (m_data == nullptr || other.m_data == nullptr) return false;

    

    return std::memcmp(m_data, other.m_data, m_length) == 0;

}


bool MyString::operator!=(const MyString& other) const {

    return !(*this == other);

}


bool MyString::operator<(const MyString& other) const {

    if (this == &other) return false;

    

    size_t min_length = std::min(m_length, other.m_length);

    

    if (m_data == nullptr && other.m_data != nullptr) return true;

    if (m_data != nullptr && other.m_data == nullptr) return false;

    if (m_data == nullptr && other.m_data == nullptr) return false;

    

    int cmp_result = std::memcmp(m_data, other.m_data, min_length);

    

    if (cmp_result < 0) return true;

    if (cmp_result > 0) return false;

    

    // 如果前面部分相等,长度小的字符串较小

    return m_length < other.m_length;

}


bool MyString::operator>(const MyString& other) const {

    return other < *this;

}


bool MyString::operator<=(const MyString& other) const {

    return !(other < *this);

}


bool MyString::operator>=(const MyString& other) const {

    return !(*this < other);

}


// 与C字符串比较

bool MyString::operator==(const char* str) const {

    if (str == nullptr) return m_data == nullptr;

    if (m_data == nullptr) return str[0] == '\0';

    

    size_t str_len = std::strlen(str);

    if (m_length != str_len) return false;

    

    return std::memcmp(m_data, str, m_length) == 0;

}

```


### 5.2 查找算法实现


```cpp

// 查找子字符串(KMP算法优化版本)

size_t MyString::find(const MyString& str, size_t pos) const noexcept {

    return find(str.m_data, pos, str.m_length);

}


size_t MyString::find(const char* str, size_t pos) const noexcept {

    if (str == nullptr || str[0] == '\0') {

        return pos <= m_length ? pos : npos;

    }

    

    size_t str_len = std::strlen(str);

    return find(str, pos, str_len);

}


// 私有辅助函数:带长度的查找

size_t MyString::find(const char* str, size_t pos, size_t str_len) const noexcept {

    if (pos >= m_length || str_len == 0 || str_len > m_length - pos) {

        return npos;

    }

    

    // 简单实现(实际可用KMP或Boyer-Moore优化)

    for (size_t i = pos; i <= m_length - str_len; ++i) {

        if (std::memcmp(m_data + i, str, str_len) == 0) {

            return i;

        }

    }

    

    return npos;

}


// 查找单个字符

size_t MyString::find(char ch, size_t pos) const noexcept {

    if (pos >= m_length || m_data == nullptr) {

        return npos;

    }

    

    const char* result = static_cast<const char*>(

        std::memchr(m_data + pos, ch, m_length - pos));

    

    return result ? result - m_data : npos;

}


// 反向查找

size_t MyString::rfind(const MyString& str, size_t pos) const noexcept {

    if (str.m_length > m_length) {

        return npos;

    }

    

    pos = std::min(pos, m_length - str.m_length);

    

    for (size_t i = pos + 1; i > 0; --i) {

        size_t current_pos = i - 1;

        if (std::memcmp(m_data + current_pos, str.m_data, str.m_length) == 0) {

            return current_pos;

        }

    }

    

    return npos;

}


// 查找第一个匹配字符

size_t MyString::find_first_of(const char* chars, size_t pos) const noexcept {

    if (pos >= m_length || chars == nullptr || chars[0] == '\0') {

        return npos;

    }

    

    for (size_t i = pos; i < m_length; ++i) {

        if (std::strchr(chars, m_data[i]) != nullptr) {

            return i;

        }

    }

    

    return npos;

}

```


## 6. 子串操作与流处理


### 6.1 子串提取


```cpp

// 提取子串

MyString MyString::substr(size_t pos, size_t count) const {

    if (pos > m_length) {

        throw std::out_of_range("MyString::substr - position out of range");

    }

    

    size_t actual_count = std::min(count, m_length - pos);

    

    MyString result;

    if (actual_count > 0) {

        result.m_length = actual_count;

        result.m_capacity = result.calculate_new_capacity(actual_count);

        result.m_data = new char[result.m_capacity + 1];

<"wap.g1k5.org.cn"><"rw.g1k5.org.cn"><"qm.g1k5.org.cn">

        

        std::memcpy(result.m_data, m_data + pos, actual_count);

        result.m_data[actual_count] = '\0';

    }

    

    return result;

}


// 替换操作

MyString& MyString::replace(size_t pos, size_t count, const MyString& str) {

    if (pos > m_length) {

        throw std::out_of_range("MyString::replace - position out of range");

    }

    

    count = std::min(count, m_length - pos);

    

    size_t new_length = m_length - count + str.m_length;

    

    if (new_length > m_capacity) {

        // 需要重新分配内存

        size_t new_capacity = calculate_new_capacity(new_length);

        char* new_data = new char[new_capacity + 1];

        

        // 复制替换点前的部分

        std::memcpy(new_data, m_data, pos);

        

        // 复制新字符串

        std::memcpy(new_data + pos, str.m_data, str.m_length);

        

        // 复制替换点后的部分

        std::memcpy(new_data + pos + str.m_length,

                   m_data + pos + count,

                   m_length - pos - count);

        

        delete[] m_data;

        m_data = new_data;

        m_capacity = new_capacity;

    } else {

        // 在现有内存中操作

        if (str.m_length != count) {

            // 需要移动数据

            std::memmove(m_data + pos + str.m_length,

                        m_data + pos + count,

                        m_length - pos - count);

        }

        

        // 复制新数据

        std::memcpy(m_data + pos, str.m_data, str.m_length);

    }

    

    m_length = new_length;

    m_data[m_length] = '\0';

    

    return *this;

}

```


### 6.2 流操作符实现


```cpp

// 输出流运算符

std::ostream& operator<<(std::ostream& os, const MyString& str) {

    if (str.m_data != nullptr) {

        os.write(str.m_data, static_cast<std::streamsize>(str.m_length));

    }

    return os;

}


// 输入流运算符

std::istream& operator>>(std::istream& is, MyString& str) {

    str.clear();

    

    // 跳过前导空白字符

    char ch;

    while (is.get(ch) && std::isspace(static_cast<unsigned char>(ch))) {

        // 跳过空白

    }

    

    if (!is) {

        return is;  // 读取失败

    }

    

    // 读取第一个非空白字符

    do {

        str.append(&ch, 1);

    } while (is.get(ch) && !std::isspace(static_cast<unsigned char>(ch)));

    

    // 如果读取到了空白字符,放回流中

    if (is && std::isspace(static_cast<unsigned char>(ch))) {

        is.putback(ch);

    }

    

    return is;

}


// 读取整行

std::istream& getline(std::istream& is, MyString& str, char delim) {

    str.clear();

    

    char ch;

    while (is.get(ch) && ch != delim) {

        str.append(&ch, 1);

    }

    

    return is;

}


// 全局运算符:字符串连接

MyString operator+(const MyString& lhs, const MyString& rhs) {

    MyString result(lhs);

    result.append(rhs);

    return result;

}


MyString operator+(const MyString& lhs, const char* rhs) {

    MyString result(lhs);

    result.append(rhs);

    return result;

}


MyString operator+(const char* lhs, const MyString& rhs) {

    MyString result(lhs);

    result.append(rhs);

    return result;

}

```


## 7. 性能优化与异常安全


### 7.1 短字符串优化(SSO)实现


```cpp

// SSO版本MyString(C++11后常见优化)

class MyStringSSO {

private:

    static constexpr size_t SSO_BUFFER_SIZE = 15;  // 短字符串缓冲区大小

    

    struct LongString {

        char* data;

        size_t length;

        size_t capacity;

    };

    

    union {

        char sso_buffer[SSO_BUFFER_SIZE + 1];  // +1 for '\0'

        LongString long_string;

    };

    

    bool is_short;  // 标记是否为短字符串

    

    size_t get_capacity() const {

        return is_short ? SSO_BUFFER_SIZE : long_string.capacity;

    }

    

    const char* get_data() const {

        return is_short ? sso_buffer : long_string.data;

    }

    

    char* get_data() {

        return is_short ? sso_buffer : long_string.data;

    }

    

    size_t get_length() const {

        return is_short 

            ? std::strlen(sso_buffer) 

            : long_string.length;

    }

    

    void set_length(size_t len) {

        if (is_short) {

            sso_buffer[len] = '\0';

        } else {

            long_string.length = len;

            long_string.data[len] = '\0';

        }

    }

    

    // 从短字符串切换到长字符串

    void convert_to_long(size_t required_capacity) {

        if (!is_short) return;

        

        size_t current_len = std::strlen(sso_buffer);

        size_t new_capacity = std::max(required_capacity, SSO_BUFFER_SIZE * 2);

        

        char* new_data = new char[new_capacity + 1];

        std::memcpy(new_data, sso_buffer, current_len + 1);

        

        long_string.data = new_data;

        long_string.length = current_len;

        long_string.capacity = new_capacity;

        is_short = false;

    }

    

public:

    // 构造函数

    MyStringSSO() : is_short(true) {

        sso_buffer[0] = '\0';

    }

    

    MyStringSSO(const char* str) {

        size_t len = std::strlen(str);

        

        if (len <= SSO_BUFFER_SIZE) {

            // 使用短字符串优化

            std::memcpy(sso_buffer, str, len + 1);

            is_short = true;

        } else {

            // 使用长字符串

            long_string.capacity = len * 2;  // 预分配额外空间

            long_string.data = new char[long_string.capacity + 1];

            std::memcpy(long_string.data, str, len + 1);

            long_string.length = len;

            is_short = false;

        }

    }

    

    // 拷贝构造函数(需考虑SSO)

    MyStringSSO(const MyStringSSO& other) {

        if (other.is_short) {

            std::memcpy(sso_buffer, other.sso_buffer, SSO_BUFFER_SIZE + 1);

            is_short = true;

        } else {

            long_string.capacity = other.long_string.capacity;

            long_string.length = other.long_string.length;

            long_string.data = new char[long_string.capacity + 1];

            std::memcpy(long_string.data, other.long_string.data, 

                       long_string.length + 1);

            is_short = false;

        }

    }

    

    // 析构函数

    ~MyStringSSO() {

        if (!is_short) {

            delete[] long_string.data;

        }

    }

    

    // 追加操作(自动处理SSO转换)

    MyStringSSO& append(const char* str, size_t len) {

        size_t current_len = get_length();

        size_t new_len = current_len + len;

        

        if (is_short && new_len <= SSO_BUFFER_SIZE) {

            // 仍使用SSO

            std::memcpy(sso_buffer + current_len, str, len);

            sso_buffer[new_len] = '\0';

        } else {

            // 需要转换或重新分配

            if (is_short || new_len > get_capacity()) {

                convert_to_long(new_len);

            }

            

            std::memcpy(long_string.data + current_len, str, len);

            long_string.length = new_len;

            long_string.data[new_len] = '\0';

        }

        

        return *this;

    }

    

    // 其他方法类似,需要考虑SSO状态

};

```


### 7.2 异常安全保证


```cpp

// 强异常安全保证的实现示例

class ExceptionSafeString {

private:

    char* data;

    size_t length;

    size_t capacity;

    

    // 私有辅助函数:创建新字符串(异常安全)

    static char* allocate_and_copy(const char* src, size_t len, size_t cap) {

        char* new_data = nullptr;

        try {

            new_data = new char[cap + 1];

            if (src != nullptr && len > 0) {

                std::memcpy(new_data, src, len);

            }

            new_data[len] = '\0';

        } catch (...) {

            delete[] new_data;

            throw;  // 重新抛出异常

        }

        return new_data;

    }

    

public:

    // 强异常安全的赋值运算符

    ExceptionSafeString& operator=(const ExceptionSafeString& other) {

        if (this != &other) {

            // 先创建新数据

            size_t new_capacity = std::max(capacity, other.length);

            char* new_data = allocate_and_copy(other.data, other.length, new_capacity);

            

            // 再替换旧数据(这个操作不会抛出异常)

            delete[] data;

            data = new_data;

            length = other.length;

            capacity = new_capacity;

        }

        return *this;

    }

    

    // 强异常安全的插入操作

    void insert(size_t pos, const char* str, size_t str_len) {

        if (pos > length) {

            throw std::out_of_range("position out of range");

        }

        

        size_t new_length = length + str_len;

        size_t new_capacity = capacity;

        

        // 计算新容量

        while (new_capacity < new_length) {

            new_capacity = new_capacity == 0 ? 16 : new_capacity * 2;

        }

        

        // 分配新内存(可能抛出异常)

        char* new_data = allocate_and_copy(nullptr, 0, new_capacity);

        

        try {

            // 复制插入点前的部分

            if (pos > 0) {

                std::memcpy(new_data, data, pos);

            }

            

            // 复制插入的字符串

            if (str_len > 0) {

                std::memcpy(new_data + pos, str, str_len);

            }

            

            // 复制插入点后的部分

            if (pos < length) {

                std::memcpy(new_data + pos + str_len, 

                           data + pos, 

                           length - pos);

            }

            

            new_data[new_length] = '\0';

            

        } catch (...) {

            delete[] new_data;

            throw;

        }

        

        // 替换旧数据(这个操作不会抛出异常)

        delete[] data;

        data = new_data;

        length = new_length;

        capacity = new_capacity;

    }

};

```


## 结语:string实现的设计权衡


通过完整实现一个string类,我们深入理解了动态内存管理、值语义、异常安全和性能优化等多个关键主题。现代C++标准库中的string实现远比我们的示例复杂,它需要考虑:


1. **内存分配策略**:SSO、内存池等优化

2. **线程安全性**:多线程环境下的安全访问

3. **标准兼容性**:严格遵循C++标准要求

4. **平台适配**:不同编译器和操作系统的差异


实际开发中,除非有特殊需求,建议直接使用标准库的string。但理解其实现原理对于编写高效、安全的C++代码至关重要。通过这种"从零实现"的学习方式,我们不仅掌握了string的工作原理,更深化了对C++核心概念的理解。


记住,好的string实现需要在功能完整性、性能效率和代码复杂度之间找到平衡点。持续学习和实践这些底层实现原理,将帮助我们在面对更复杂的系统设计时做出明智的架构决策。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3106936/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    933493