当前位置: 首页 > news >正文

string接口的模拟实现

文章目录

  • 一. string底层逻辑
    • 演示声明和定义分开
  • 二. size()
  • 三. operator[]
  • 四. 迭代器
  • 四. const迭代器
  • 五. 预留空间(reserve)
  • 六. 尾插一个字符push_back
  • 七. 尾插一个字符串append
  • 八. operator+=
  • 九. operator+=

一. string底层逻辑

(1)为了和库里面的string类区分开,我们可以使用命名空间(hou)。之前学习的命名空间就有了价值。
(2)在类里面的都是内联函数在这里插入图片描述
(3)对于比较短小的函数,直接在类里面写就行。函数大一点,将声明和定义分开。

  1. 成员变量
#include<stdio.h>
#include<string>
#include<iostream>
namespace hou
{class string{private:char* _str;    //char类型数据数组的地址size_t _size;  //有效元素个数size_t _capacity; //空间大小};
}
  1. 成员函数
    任何一个类都从构造函数开始(无参/有参)

无参的话,将三个成员变量初始化为什么呢?都初始化为空吗?

这样是不可以的。
记得:const char*比较特殊,cout它不会打印出地址,它自动识别类型,会以为打印字符串(字符串的打印规则是遇到‘\0’才会终止),而我们的_str是空指针,将空指针解引用,肯定是错误的(本质是空指针问题)
在这里插入图片描述



---------------在这里插入图片描述
所以,不能将char*初始化为空。里面起码要放一个'\0'
在这里插入图片描述

namespace hou
{class string{public://任何一个类都从构造函数开始string()//先写一个无参的构造函数:_str(new char[1]{'\0'}),_size(0),_capacity(0){}~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}const char* c_str()const{return _str;}private:char* _str;    //char类型数据数组的地址size_t _size;  //有效元素个数size_t _capacity; //空间大小};
}

刚刚写了无参的构造函数,接下来写一个有参的构造函数
注意点:

  1. strlen计算长度时,不包括'\0'
  2. strlen是在运行时计算的,size是编译时计算的
  3. 在初始化列表里写,它的初始化顺序是按照声明的顺序来的
    在这里插入图片描述
    之前我们说过,尽可能使用初始化列表,但是strlen是在运行时计算的,要计算3次,效率低。这样子的话,我们可以将strlen先计算出来,之后用。但记住,初始化列表的顺序是按照声明的顺序。

演示声明和定义分开

当我们想把声明写在.h里面,定义写在.cpp里面的时候
在这里插入图片描述
这样写会报错,所以我们需要在string.cpp里(1)写上类域(2)再写一下命名空间
一个命名空间是可以写多个的,多个文件的同一个命名空间会被合并为(认为)一个命名空间的
在这里插入图片描述




在这里插入图片描述

已经声明和定义了,还有一个需要注意的内容是,缺省值只能在声明的时候给(定义那里不可以写缺省值)。但是char* _str的缺省值不可以是nullptr,可以给一个'\0'或者直接“”(字符串默认后面会加'\0'的)

二. size()

  • 对象.size()就是为了得到对象的大小(即对象的有效元素个数)

如果声明和定义分开写了,同时这个函数有返回值,那string::加到哪里呢?

在这里插入图片描述

三. operator[]

string.cpp里面的内容

char& string::operator[](size_t i)
{return _str[i];
}

四. 迭代器

string的迭代器(string的物理结构是数组)

using iterator = char*;
//typedef char* iterator;

迭代器还需要配合begin()end()(begin()就是返回开始位置的迭代器)

using iterator = char*;
iterator string::begin()
{return _str;
}
iterator string::end()
{return _str+_size;
}

在这里插入图片描述

范围for的底层是迭代器(支持迭代器则支持范围for)

在这里插入图片描述

四. const迭代器

在这里插入图片描述

五. 预留空间(reserve)

本质就是扩容,但是这种提高了效率,原本需要2倍2倍的扩,但是当你知道需要多大的空间时,就可以一次性扩容好。

在这里插入图片描述

  1. reserve一般不缩容,我们需要先判断一下,想扩容的大小n是否比_capacity大
  2. 开空间的时候永远要多开一个,因为’\0‘是不计入_capacity
	void string:: reserve(size_t n){if (n > _capacity){char* tmp=new char[n+1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n; //'\0'不计入空间大小}}

六. 尾插一个字符push_back

void string::push_back(char ch)
{//先判断空间大小是否足够if (_size = _capacity){//不够的话进入if语句进行扩容reserve(_capacity = 0 ? 4 : 2 * _capacity);}_str[_size] = ch;_size++;
}

七. 尾插一个字符串append

	void string::append(const char* str){size_t len = strlen(str);size_t newcapacity = 2 * _capacity < _size + len ? _size + len : 2 * _capacity;reserve(newcapacity);//开好空间之后,插入字符串strcpy(_str+_size, str);//直接复制(第一个参数是复制到哪里(位置),第二个是被复制的串)_size += len;}

八. operator+=

string& string:: operator+=(char ch)
{push_back(ch);return *this;
}

九. operator+=


string& string:: operator+=(const char* str)
{append(str);return *this;
}
http://www.lryc.cn/news/489478.html

相关文章:

  • sed使用扩展正则表达式时, -i 要写在 -r 或 -E 的后面
  • Verilog HDL可综合与不可综合语句
  • tomcat 后台部署 war 包 getshell
  • 网络云计算】2024第47周-每日【2024/11/21】周考-实操题-RAID6实操解析1
  • 前端面试题大汇总:React 篇
  • 【prism】遇到一个坑,分享!
  • Python+Selenium+Pytest+Allure+ Jenkins webUI自动化框架
  • 智象未来(HiDream.ai)技术赋能,开启AR眼镜消费时代
  • element dialog 2层弹窗数据同步问题
  • 向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)
  • 要素市场与收入分配
  • Web3的核心技术:区块链如何确保信息安全与共享
  • 2025蓝桥杯(单片机)备赛--扩展外设之UART1的原理与应用(十二)
  • Js中的常见全局函数
  • MySQL连接查询之自连接
  • Python 爬虫 (1)基础 | 基础操作
  • JAVA八股与代码实践----如何为springboot设置Servlet容器为jetty,jetty的优点是什么?
  • idea怎么打开两个窗口,运行两个项目
  • wend看源码-APISJON
  • 堆外内存泄露排查经历
  • SpringBoot Task
  • 学习路之压力测试--jmeter安装教程
  • 大模型部署,运维,测试所需掌握的知识点
  • ECharts柱状图-带圆角的堆积柱状图,附视频讲解与代码下载
  • java 并发编程 (2)Thread 类和 Runnable 接口详解
  • 人工智能之数学基础:线性代数在人工智能中的地位
  • PostgreSQL WITH 子句:提高查询效率和可读性
  • TransFormer--解码器:前馈网络层、叠加和归一组件
  • 2024亚太杯国际赛C题参考文章50页+完整解题思路+数据处理+最终结果
  • Kafka 分区分配及再平衡策略深度解析与消费者事务和数据积压的简单介绍