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

string的模拟实现与深浅拷贝

在上一章中可以看见,string类函数的基本实现和用法,在本文。来用基础的语言来模拟实现string类,来了解一下他们的基础底层;

在VS中string,我们可以看见,实现VS的类成员很多,很麻烦;

 我们自己实现为了基础理解底层时,可以把成员设的简单点;只设 char*  size  和 capacity

在实现一些成员函数时

注意事项:

防止权限扩大

要根据string函数的具体要求去实现,不要忘了实现const类型,防止权限扩大;

注意只是两个接口;一个可读可写的[ ],一个只能读的不能写的[ ]。

string输入流

std::cin 的输入 ,自动会将 空格(’ ‘) ,等认为换行符;这样在实现,string的输入流时,会导致无法输入 像we are famliy 的字符;如此就要请出 getline,这个可以自己实现换行符 是什么的std函数。 

深浅拷贝问题

因此,这里要记得为string写深拷贝,编译器自己实现的浅拷贝无法实现;

增加扩容效率

以substr为例子,可以选择直接 += 但这样会导致经常扩容,效率低;但这里能提前知道了内存大小,可以提前扩容,增加效率 

隐式类型转换

因为 _size  的类型是size 无 符号,如果将end设为int类型,如果情况是pos = 0,在减到 - 1时 进行类似类型转换,int 转为 size_t ;-1 无符号的反义码是11111111 11111111 很大;导致无限循环;

或者 换一个 循环 不访问 -1 的也行; 但最好保证类型一致;

字符串 最后存在“ \0 ”

字符串最后的"\0"存在 ,可以移动过去,要注意;

对这里提醒一下,对于这种移动数据的插入,最好少用,效率太低了,注意尽量少用,虽然很方便

    注意域限定:

海滩std的模板函数 swap 

但要注意这个std::swap,虽然存在模板,可以任意转换但是,转换中却有拷贝构造,和运算符重载,效率很低;但是方便也是确实的

参考代码

string.h 

#pragma once#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
//#include<string>
#include<assert.h>
using namespace std;namespace xryq {class string {public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}//string()//	:_str(new char[1]{ '\0' })//	,_size(0)//	,_capacity(0)//{}string(const string& s){_str = new char[s._capacity + 1];strcpy(_str, s._str);_capacity = s._capacity;_size = s._size;}//现代写法string(const string& s){string tmp(s._str);swap(s); }//构造函数重载//string(const char* str = '\0')string(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}~string(){delete[] _str;_size = _capacity = 0;}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char* c_str() const{return _str;}const size_t capacity() const{return _capacity;}const size_t size() const {return _size;}void clear(){//编译器 遇到 \0 就失效 在前面加 \0相当于清除_str[0] = '\0';//_capacity = _size = 0;//容量没有清 只是  数量变了_size = 0;}void swap(string s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}// 现代写法string& operator=(const string s){if (this != &s){swap(s);return *this;}}//末代写法//string& operator=(const string& s)//{//	if (this != &s)//	{		//		//这里先清除的主要原因是  更方便 且不会有内容浪费  等问题//		delete[] _str;//		_str = new char[s._capacity + 1];//		_capacity = s._capacity;//		_size = s._size;//	}//}void reserve(size_t n);void push_back(char ch);void append(const char* str);string& operator+=(char ch);string& operator+=(const char* str);void insert(size_t pos, char ch);void insert(size_t pos, const char* str);void erase(size_t pos, size_t len = npos);size_t find(char ch, size_t pos = 0);size_t find(const char* str, size_t pos = 0);string substr(size_t pos = 0, size_t len = npos);//static const size_t npos = -1;  这里可以 或者 只能看成 c++ 对 整形的绿色通道//static const double i = 1.1;  只有整形不报错private:char* _str;size_t _size;size_t _capacity;static const size_t npos = -1;};void text_string1();void text_string2();bool operator<(const string& s1, const string& s2);bool operator<=(const string& s1, const string& s2);bool operator>(const string& s1, const string& s2);bool operator>=(const string& s1, const string& s2);bool operator==(const string& s1, const string& s2);bool operator!=(const string& s1, const string& s2);ostream& operator<<(ostream& out, const string& s);istream& operator>>(istream& in, string& s);}

string.cpp


#include"string.h"namespace xryq{//static const size_t npos = -1;void string::reserve(size_t n){assert(n > _capacity);cout << n << endl;char* tmp = new char[n + 1];_capacity = n;strcpy(tmp, _str);_str = tmp;}void string::push_back(char ch){if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;}string& string::operator+=(char ch){push_back(ch);return *this;}string& string::operator+=(const char* str){append(str);return *this;}void string::append(const char* str){size_t len = strlen(str);if(_size + len > _capacity)reserve(_size + len > _capacity * 2 ? _size + len : _capacity * 2);strcpy(_str + _size, str);_size += len;}void string::insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size;//int end = _size + 1;//这是c语言 留下来的一个坑;如果比较时 类型不一样那么就会 //进行隐式类型转换   小向大 的转换  int 向 unsign的转换while (end >= pos){_str[end + 1] = _str[end];--end;}_str[end] = ch;++_size;//或者 不访问-1也许//while (end > pos)//{//	_str[end] = _str[end - 1];//	--end;//}//_str[end] = ch;//++_size;}void string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len > _capacity * 2 ? _size + len : _capacity * 2);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];--end;}for (int i = 0; i < len; ++i){_str[pos + i] = str[i];}_size += len;}void string::erase(size_t pos, size_t len){assert(pos < _size);if (len >= _size - pos){_str[pos] = '\0';_size = pos;}else {//for (size_t i = 0; i < _size - pos - 1 - len; ++i)//{//	_str[pos + i] = _str[pos + len + i];//}//_str[_size - 1 - len] = '\0';//最后一个字符是\0for (size_t i = 0; i <= _size - pos - len; ++i){_str[pos + i] = _str[pos + len + i];}_size -= len;}}size_t string::find(char ch, size_t pos){assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;}size_t string::find(const char* str, size_t pos){assert(pos < _size);const char* ch = strstr(_str, str);for (size_t i = pos; i < _size; ++i){if (_str[i] = *ch){return i;}}return npos;}string string::substr(size_t pos, size_t len){assert(pos < _size);string tmp;if (_size - pos <= len){len = _size - pos;}//提前算好空间 提高效率tmp.reserve(len);for (size_t i = 0; i <= len; ++i){tmp += _str[i + pos];}return tmp;}ostream& operator<<(ostream& out, const string& s){for (auto i : s){out << i;}//cout << s.c_str();return out;}istream& operator>>(istream& in, string& s){s.clear();char ch;ch = in.get();while (ch != ' ' && ch != '\n'){s += ch;ch = in.get();}return in;}//上面的牵扯到 多次扩容  效率比较低//istream& operator>>(istream& in, string& s)//{//	s.clear();//	char ch;//	const int N = 256;//	char buff[N];//	int i = 0;//	ch = in.get();//	while (ch != ' ' && ch != '\n')//	{//		buff[i] = ch;//		i++;//		if (i == N - 1)//		{//			buff[i] = '\0';//			s += buff;//			i = 0;//		}//		ch = in.get();//	}//	if (i > 0)//	{//		buff[i] = '\0';//		s += buff;//	}//	return in;//}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 嵌入式全栈开发学习笔记---Linux系统编程(进程间通信)
  • Trying to update a textarea with string from an OpenAI request
  • 使用Python+docx+openpyxl将Word表格转换为Excel表格
  • 如何处理时间序列异常值?理解、检测和替换时间序列中的异常值
  • 掌握Go语言中的Channel:并发编程的核心
  • 集成电路学习:什么是CPU中央处理器
  • 神仙插件 LightFlow!一键复用SD WebUI工作流,AI绘画StableDiffusion抄作业必备神器!
  • 【Python篇】Python 类和对象:详细讲解(上篇)
  • 海外新闻稿发布:企业如何充分利用数字化媒体进行
  • [imx9]DDR test Tool for imx9
  • HarmonyOS鸿蒙开发:在线短视频流畅切换最佳实践
  • 数据结构——队的基本操作
  • MongonDB-索引
  • 集成电路学习:什么是ARM先进精简指令集计算机
  • 旗帜分田(华为od机考题)
  • JavaScript 如何正确处理 Unicode 编码问题!
  • @jsonView过滤属性
  • C++入门教程(10):for 语句
  • css的样式优先级
  • es6--symbol
  • es的写入过程
  • k8s如何管理Pod
  • 对象引论
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 浮现式设计
  • 简析gRPC client 连接管理
  • 思考 CSS 架构
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 系统认识JavaScript正则表达式
  • 异常机制详解
  • 06-01 点餐小程序前台界面搭建
  • ​人工智能书单(数学基础篇)
  • ![CDATA[ ]] 是什么东东
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #git 撤消对文件的更改
  • (Git) gitignore基础使用
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (规划)24届春招和25届暑假实习路线准备规划
  • (推荐)叮当——中文语音对话机器人
  • (五)IO流之ByteArrayInput/OutputStream
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (杂交版)植物大战僵尸
  • .apk 成为历史!
  • .DFS.
  • .env.development、.env.production、.env.staging
  • .net mvc 获取url中controller和action
  • .Net mvc总结
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • .NET开发不可不知、不可不用的辅助类(一)
  • .net知识和学习方法系列(二十一)CLR-枚举
  • /usr/bin/env: node: No such file or directory
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @Autowired多个相同类型bean装配问题
  • @Autowired和@Resource的区别