C++之string的模拟实现

string

  • 手写C++字符串类
      • 类的基本结构与成员变量
      • 一、构造函数与析构函数
      • 二、赋值运算符重载
      • 三、迭代器支持
      • 四、内存管理与扩容机制
      • 五、字符串操作函数
      • 六、运算符重载
      • 总结

在这里插入图片描述

手写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,但掌握这些底层原理有助于写出更高效、更安全的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

修改Docker镜像源

配置文件位置&#xff1a; sudo vim /etc/docker/daemon.json Docker 或 containerd 的镜像加速器配置&#xff0c;旨在提高从 Docker Hub 拉取镜像的速度。 { "features": { "buildkit": true, "containerd-snapshotter": true }, …

服务器带宽线路的区别(GIA、CN2、BGP、CMI等)

服务器带宽线路的区别&#xff08;GIA、CN2、BGP、CMI等&#xff09; 一、BGP线路 1. 定义与技术特点 BGP&#xff08;Border Gateway Protocol&#xff0c;边界网关协议&#xff09;是一种用于不同自治系统&#xff08;AS&#xff09;之间交换路由信息的协议&#xff0c;属…

从0到1搭建AI绘画模型:Stable Diffusion微调全流程避坑指南

从0到1搭建AI绘画模型&#xff1a;Stable Diffusion微调全流程避坑指南 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 从0到1搭建AI绘画模型&#xff1a;Stable Diffusion微调全流程避坑指南摘要引言一、数据集构…

VSCode + GD32F407 构建烧录

前言 最近调试一块 GD32F407VET6&#xff08;168Mhz&#xff0c;8Mhz晶振&#xff09; 板子时&#xff0c;踩了一些“启动失败”的坑。本以为是时钟配置有误&#xff0c;最后发现是链接脚本&#xff08;.ld 文件&#xff09;没有配置好&#xff0c;导致程序根本没能正常执行 ma…

AI绘画提示词:从零开始掌握Prompt Engineering的艺术

文章目录 什么是AI绘画提示词&#xff1f;提示词的基本结构主体描述场景/背景风格指定技术参数负面提示人物肖像模板风景模板 高级技巧权重调整混合风格颜色控制情绪氛围 常见问题与解决方法手部变形问题构图不理想风格不够突出 提示词示例库科幻场景奇幻人物静物画 结语 在当今…

在 Linux 上安装 Minikube:轻松搭建本地 Kubernetes 单节点集群

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、Minikube 是什么&#xff1f; Minikube 是 Kubernetes 官方推出的轻量级工具&#xff0c;专为开发者设计&#xff0c;用于在本地快速搭建单节点 Kube…

day41 python图像识别任务

目录 一、数据预处理&#xff1a;为模型打下坚实基础 二、模型构建&#xff1a;多层感知机的实现 三、训练过程&#xff1a;迭代优化与性能评估 四、测试结果&#xff1a;模型性能的最终检验 五、总结与展望 在深度学习的旅程中&#xff0c;多层感知机&#xff08;MLP&…

JS数组 concat() 与扩展运算符的深度解析与最佳实践

文章目录 前言一、语法对比1. Array.prototype.concat()2. 扩展运算符&#xff08;解构赋值&#xff09; 二、性能差异&#xff08;大规模数组&#xff09;关键差异原因 三、适用场景建议总结 前言 最近工作中遇到了一个大规模数组合并相关的问题&#xff0c;在数据合并时有些…

一套qt c++的串口通信

实现了创建线程使用串口的功能 具备功能: 1.线程使用串口 2.定时发送队列内容&#xff0c;防止粘包 3.没处理接收粘包&#xff0c;根据你的需求来&#xff0c;handleReadyRead函数中&#xff0c;可以通过m_receiveBuffer来缓存接收&#xff0c;然后拆分数据来处理 源码 seri…

设计模式-发布订阅

文章目录 发布订阅概念发布订阅 vs 监听者例子代码 发布订阅概念 发布/订阅者模式最大的特点就是实现了松耦合&#xff0c;也就是说你可以让发布者发布消息、订阅者接受消息&#xff0c;而不是寻找一种方式把两个分离 的系统连接在一起。当然这种松耦合也是发布/订阅者模式最大…

windows-cmd 如何查询cpu、内存、磁盘的使用情况

在 Windows 中&#xff0c;您可以使用命令提示符&#xff08;CMD&#xff09;通过一些命令来查询 CPU、内存和磁盘的使用情况。以下是常用的命令和方法&#xff1a; 1. 查询 CPU 使用情况 使用 wmic 命令 wmic cpu get loadpercentage 这个命令会显示当前 CPU 的使用百分比…

allWebPlugin中间件VLC专用版之截图功能介绍

背景 VLC控件原有接口具有视频截图方法&#xff0c;即video对象的takeSnapshot方法&#xff0c;但是该方法返回的是一个IPicture对象&#xff0c;不适合在谷歌等现代浏览器上使用。因此&#xff0c;本人增加一个新的视频截图方法takeSnapshot2B64方法&#xff0c;直接将视频截图…

第Y5周:yolo.py文件解读

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 本次任务&#xff1a;将YOLOv5s网络模型中的C3模块按照下图方式修改形成C2模块&#xff0c;并将C2模块插入第2层与第3层之间&#xff0c;且跑通YOLOv5s。 任务…

宝塔安装ssh证书报错:/usr/bin/curl: symbol lookup error: curl_easy_header

原因&#xff1a; 你当前的 curl 命令版本是 7.70.0&#xff08;不是系统默认版本&#xff0c;应该是你手动安装的&#xff09;。它链接的是 /usr/local/lib/libcurl.so.4&#xff0c;而不是 CentOS 系统默认的 /usr/lib64/libcurl.so.4。/usr/local/lib/libcurl.so.4 很可能是…

Apache SeaTunnel 引擎深度解析:原理、技术与高效实践

Apache SeaTunnel 作为新一代高性能分布式数据集成平台&#xff0c;其核心引擎设计融合了现代大数据处理架构的精髓。 Apache SeaTunnel引擎通过分布式架构革新、精细化资源控制及企业级可靠性设计&#xff0c;显著提升了数据集成管道的执行效率与运维体验。其模块化设计允许用…

测试用例及黑盒测试方法

一、测试用例 1.1 基本要素 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合&#xff0c;这组集合包含&#xff1a;测试环境、操作步骤、测试数据、预期结果等4个主要要素。 1.1.1 测试环境 定义&#xff1a;测试执行所需的软硬件…

硬件工程师笔记——运算放大电路Multisim电路仿真实验汇总

目录 1 运算放大电路基础 1.1 概述 1.1.1 基本结构 1.1.2 理想特性 1.2 运算放大分析方法 1.2.1 虚短 1.2.2虚断 1.2.3 叠加定理 2 同向比例运算放大电路 2.1 概述 2.1.1 基本电路结构 2.1.2 电路原理 2.2 仿真分析 2.2.1 电压增益 2.2.2 相位分析 3 反向比例运…

板凳-------Mysql cookbook学习 (九)

第4章&#xff1a;表管理 4.0 引言 MySQL &#xff1a;&#xff1a; 员工样例数据库 &#xff1a;&#xff1a; 3 安装 https://dev.mysql.com/doc/employee/en/employees-installation.html Employees 数据库与几种不同的 存储引擎&#xff0c;默认情况下启用 InnoDB 引擎。编…

MySQL省市区数据表

数据结构简单展示一下 具体的可以点击文章最后的链接地址下载 连接地址中有两个文件一个是详细的另一个是简洁的 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for ln_new_region -- ---------------------------- DROP…

无人机报警器探测模块技术解析!

一、运行方式 1. 频谱监测与信号识别 全频段扫描&#xff1a;模块实时扫描900MHz、1.5GHz、2.4GHz、5.8GHz等无人机常用频段&#xff0c;覆盖遥控、图传及GPS导航信号。 多路分集技术&#xff1a;采用多传感器阵列&#xff0c;通过信号加权合并提升信噪比&#xff0c;…