C++之string的模拟实现过程

 更新时间:2025年06月03日 10:55:51   作者:zzh_zao  
这篇文章主要介绍了C++之string的模拟实现过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

手写C++字符串类

从零实现一个简易版std::string

类的基本结构与成员变量

namespace zzh {
class string {
private:
    char* _str;        // 存储字符串的字符数组
    size_t _size;      // 当前字符串长度
    size_t _capacity;  // 已分配的容量
public:
    static const size_t npos;  // 表示"不存在的位置"
    // 各类成员函数...
};
}

这个自定义字符串类主要通过动态分配的字符数组_str来存储字符串内容,并维护两个重要状态:_size表示当前字符串长度,_capacity表示已分配的内存容量。

1.基本成员变量

在自定义 string 类中,我们需要定义一些基本的成员变量来存储字符串的内容和相关信息:

  • _str:用于存储字符串的字符数组,通常是一个动态分配的 char 类型数组。
  • _size:表示当前字符串的实际长度,不包括结尾的空字符 \0。
  • _capacity:表示分配的内存容量,通常大于或等于 _size,用于优化内存分配效率。

2.构造函数和析构函数

构造函数用于初始化 string 对象,常见的构造方式包括:

  • 从 C 风格字符串构造(const char*):通过 strlen 计算字符串长度,并动态分配内存来存储字符串内容。
  • 拷贝构造函数:用于从另一个 string 对象构造新对象,需要深拷贝内存以避免悬挂指针问题。
  • 默认构造函数:用于创建一个空字符串。
  • 析构函数则负责释放动态分配的内存,避免内存泄漏。

3.赋值运算符重载

  • 为了支持对象之间的赋值操作,我们需要重载赋值运算符 =。
  • 在实现时,需要注意自赋值的情况,并进行深拷贝以确保两个对象的内存独立。

4.内存管理

  • 字符串操作中,内存管理是一个关键问题。
  • 我们需要在字符串长度超过当前容量时动态扩展内存。
  • 通常的做法是将容量加倍,以减少频繁的内存分配操作。

5.迭代器支持

  • 为了方便遍历字符串中的字符,我们可以提供迭代器支持。
  • 通过定义 begin() 和 end() 方法,返回指向字符串首尾的指针,可以方便地使用标准库算法。

6.常见操作实现

追加字符或字符串:通过 push_back 和 append 方法,可以在字符串末尾添加字符或另一个字符串的内容。在实现时,需要注意内存容量是否足够,并在必要时进行扩展。

  • 查找和替换:提供 find 方法用于查找字符或子字符串的位置,insert 和 erase 方法用于插入和删除字符或子字符串。
  • 比较操作:重载比较运算符(如 <、>、== 等),以便可以直接比较两个 string 对象的大小。

一、构造函数与析构函数

// 1. 从C风格字符串构造
string::string(const char* str)
{
    _size = strlen(str);
    _str = new char[_size + 1];
    _capacity = _size;
    memcpy(_str, str, _size + 1);
}

// 2. 拷贝构造函数
string::string(const string& s)
{
    _size = s._size;
    _capacity = s._capacity;
    _str = new char[_capacity + 1];
    memcpy(_str, s._str, _size + 1);
}

// 3. 析构函数
string::~string()
{
    delete[] _str;
    _str = nullptr;
    _size = 0;
    _capacity = 0;
}

关键点

  • 构造函数负责分配内存并复制字符串内容
  • 拷贝构造函数实现深拷贝,避免内存共享
  • 析构函数必须释放动态分配的内存,防止内存泄漏

二、赋值运算符重载

string& string::operator=(const string& s)
{
    if (this != &s)
    {
        char* tmp = new char[s._capacity + 1];
        memcpy(tmp, s._str, s._size + 1);
        delete[] _str;  // 注意:原代码此处顺序有误,已修正
        _str = tmp;
        _size = s._size;
        _capacity = s._capacity;
    }
    return *this;
}

技术要点

  • 使用临时变量确保异常安全
  • 自我赋值检查避免无效操作
  • 先分配新内存再释放旧内存,防止内存泄漏

三、迭代器支持

string::iterator string::begin() { return _str; }
string::iterator string::end() { return _str + _size; }

说明

  • 迭代器本质是字符指针
  • begin()返回字符串首地址
  • end()返回字符串末尾的下一个位置

四、内存管理与扩容机制

// 预分配内存
void string::reserve(size_t n)
{
    if (n > _capacity)
    {
        char* tmp = new char[n + 1];
        memcpy(tmp, _str, _size + 1);
        delete[] _str;
        _str = tmp;
        _capacity = n;
    }
}

// 追加字符
void string::push_back(char c)
{
    if (_size >= _capacity)
    {
        size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
        reserve(newcapacity);
    }
    _str[_size++] = c;  // 注意:原代码此处错误地写入了固定字符'c'
    _str[_size] = '\0';
}

内存管理策略

  • 采用指数级扩容(2倍)减少内存分配次数
  • reserve()实现预分配,避免频繁扩容
  • 每次扩容后保留额外空间,提高插入效率

五、字符串操作函数

// 追加C风格字符串
void string::append(const char* str)
{
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
        size_t newcapacity = 2 * _capacity > _size + len ? 2 * _capacity : _size + len;
        reserve(newcapacity);
    }
    memcpy(_str + _size, str, len);  // 注意:原代码此处多复制了一个终止符
    _size += len;
    _str[_size] = '\0';  // 手动添加终止符
}

// 查找字符
size_t string::find(char c, size_t pos = 0) const
{
    for (size_t i = pos; i < _size; i++)
    {
        if (_str[i] == c)
            return i;
    }
    return npos;
}

// 插入字符
string& string::insert(size_t pos, char c)
{
    assert(pos <= _size);
    if (_size >= _capacity)
    {
        size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
        reserve(newcapacity);
    }
    // 从后向前移动元素
    for (size_t i = _size; i > pos; i--)
        _str[i] = _str[i - 1];
    _str[pos] = c;
    _size++;
    return *this;
}

核心算法

  • append()通过内存拷贝实现高效追加
  • find()线性查找目标字符
  • insert()通过元素后移实现插入操作
  • 使用memmove()处理内存重叠情况

六、运算符重载

// 比较运算符
bool string::operator<(const string& s)
{
    size_t i1 = 0, i2 = 0;
    while (i1 < _size && i2 < s._size)
    {
        if (_str[i1] < s._str[i2])
            return true;
        else if (_str[i1] > s._str[i2])
            return false;
        i1++; i2++;
    }
    return i1 < s._size;  // 注意:原代码此处逻辑有误,已修正
}

// 索引运算符
char& string::operator[](size_t index)
{
    assert(index < _size);
    return _str[index];
}

实现要点

  • 比较运算符按字典序逐字符比较
  • 索引运算符提供随机访问能力
  • 提供常量和非常量两个版本的重载

总结

通过手写这个简易版string类,我们深入理解了标准库字符串类的核心机制:动态内存管理、深拷贝实现、迭代器设计、扩容策略等。

虽然现代C++编程中应优先使用std::string,但掌握这些底层原理有助于写出更高效、更安全的代码。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C++使用标准库实现事件和委托以及信号和槽机制

    C++使用标准库实现事件和委托以及信号和槽机制

    这篇文章主要为大家详细介绍了C++如何使用标准库实现事件和委托以及信号和槽机制,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-11-11
  • C语言完数的实现示例

    C语言完数的实现示例

    C语言中的完数指的是一个正整数,本文主要介绍了C语言完数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • C++日期类运算符重载方式

    C++日期类运算符重载方式

    这篇文章主要介绍了C++日期类运算符重载方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 最小生成树算法C语言代码实例

    最小生成树算法C语言代码实例

    这篇文章主要介绍了最小生成树算法C语言代码实例,有需要的朋友可以参考一下
    2013-12-12
  • C++实现冒泡排序(BubbleSort)

    C++实现冒泡排序(BubbleSort)

    这篇文章主要为大家详细介绍了C++实现冒泡排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 简单掌握C++编程中的while与do-while循环语句使用

    简单掌握C++编程中的while与do-while循环语句使用

    这篇文章主要介绍了C++编程中的while与do-while循环语句使用,区别就是while是先判断再执行,而do-while是先执行再判断,需要的朋友可以参考下
    2016-01-01
  • Cocos2d-x UI开发之文本类使用实例

    Cocos2d-x UI开发之文本类使用实例

    这篇文章主要介绍了Cocos2d-x学习笔记之文本类,文本类是UI开发中经常使用的,本文用详细的代码注释讲解了文本类的使用,需要的朋友可以参考下
    2014-09-09
  • C++实现完整功能的通讯录管理系统详解

    C++实现完整功能的通讯录管理系统详解

    来了来了,通讯录管理系统踏着七彩祥云飞来了,结合前面的结构体知识和分文件编写方法,我总结并码了一个带菜单的通讯录管理系统,在这篇文章中将会提到C的清空屏幕函数,嵌套结构体具体实现,简单且充实,跟着我的思路,可以很清晰的解决这个项目
    2022-05-05
  • 利用C语言编写一个无限循环语句

    利用C语言编写一个无限循环语句

    这篇文章主要介绍了利用C语言编写一个无限循环语句问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C++模拟Linux Shell编写一个自定义命令

    C++模拟Linux Shell编写一个自定义命令

    这篇文章主要介绍了C++如何模拟Linux Shell实现编写一个自定义命令,本文通过实例代码进行命令行解析,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12

最新评论