C++ string类(二)及深浅拷贝

news/2024/3/29 15:08:54/文章来源:https://blog.csdn.net/weixin_59215611/article/details/129224688

一、string类方法使用举例

1.迭代器

迭代器本质:指针(理解)

迭代器:正向迭代器: begin() | end() 反向迭代器: rbegin() | rend()

2.find使用

//找到s中某个字符
void TestString3()
{string s("AAADEFNUIENFUIAAA");//找到AAA位置size_t pos = s.find("AAA");cout << pos << endl;
}

输出0,表示0位置处为AAA

3.获取文件后缀/substr

substr(pos = 0, n = npos);

从Pos位置开始,截取n个字符,如果n没有传递,表示从pos一直截取到末尾

如果都没有传递,截取整个字符

void TestString3()
{string s("124.text.cpp");//rfind从后面往前找 ’.’,+1找到后缀位置size_t pos =s.rfind('.') + 1;//从pos处截到末尾string postfix = s.substr(pos);cout << postfix << endl;
}

4.给多行单词,获取每行单词中最后一个单词的长度/getline

int main()
{string line;// 不要使用cin>>line,因为会它遇到空格就结束了// while(cin>>line)while (getline(cin, line)){size_t pos = line.rfind(' ');cout << line.size() - pos - 1 << endl;}return 0;
}

getline(cin,s): 获取一整行字符串,字符串中如果包含空格等空白字符也可以接收

oj练习

5.比大小

void Test()
{string s1("abc");string s2("afwef");if (s1 < s2){cout << "s1<s2" << endl;}else if (s1>s2){cout << "s1>s2" << endl;}else{cout << "s1=s2" << endl;}
}

6.其他一些练习OJ

反转字母OJ

找第一个出现的相同的字符

验证回文串

二. string类的模拟实现

1. 浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规

上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝

2、解决浅拷贝的方法:深拷贝,写时拷贝(了解)

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供

3.String类的模拟实现

正确实现String

深拷贝,传统版本

class String
{
public:String(const char* str = ""){if (nullptr == str)str == "";_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s):_str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}String& operator=(const String& s){if (this != &s){char* pStr = new char[strlen(s._str) + 1];strcpy(pStr, s._str);delete[] _str;_str = pStr;}return *this;}~String(){if (_str){delete[]_str;_str = nullptr;}}
private:char* _str;
};void TestString()
{String s1("hello");String s2(s1);String s3(s2);
}
int main()
{TestString();return 0;
}

如下,每个对象都有自己独立的空间,释放时也是,只释放自己的互不影响

深拷贝(现代版写法)

减少传统代码重复,相似性代码进行优化

class String
{
public:String(const char* str = ""){if (nullptr == str){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s): _str(nullptr)//_Str可能为随机指针,要先置为空{String strTmp(s._str);swap(_str, strTmp._str);//交换地址}String& operator=(String s)//赋值运算符重载,先传入参数{swap(_str, s._str);//return *this;}

4.写时拷贝

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。

引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源

三、string模拟实现代码(全部)

#include <assert.h>
#include<iostream>
#include<string>
using namespace std;
namespace zx
{class string{public:typedef char* iterator;///// 构造string(const char* str = ""){if (nullptr == str)str = "";_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}string(const string& s){string temp(s._str);this->swap(temp);}string(size_t n, char val){_str = new char[n + 1];memset(_str, val, n);_str[n] = '\0';_size = n;_capacity = n;}string& operator=(string s){this->swap(s);return *this;}~string(){if (_str){delete[] _str;_str = nullptr;_capacity = 0;_size = 0;}}/// 迭代器iterator begin(){return _str;}iterator end(){return _str + _size;}/// 容量size_t size()const{return _size;}size_t length()const{return _size;}size_t capacity()const{return _capacity;}bool empty()const{return 0 == _size;}void clear(){_size = 0;}void resize(size_t newsize, char val){size_t oldsize = size();if (newsize > oldsize){// 有效元素个数增多if (newsize > capacity())reserve(newsize);// 多出的元素使用val填充memset(_str + _size, val, newsize - _size);}_size = newsize;_str[_size] = '\0';}void resize(size_t newsize){resize(newsize, '\0');}void reserve(size_t newcapacity){size_t oldcapacity = capacity();if (newcapacity > oldcapacity){// 1. 申请新空间char* temp = new char[newcapacity + 1];// 2. 拷贝元素strncpy(temp, _str, _size);// 3. 释放旧空间delete[] _str;// 4. 使用新空间_str = temp;_capacity = newcapacity;_str[_size] = '\0';}}// 元素访问char& operator[](size_t index){assert(index < _size);return _str[index];}const char& operator[](size_t index)const{assert(index < _size);return _str[index];}char& at(size_t index){// 如果越界,抛出out_of_range的异常return _str[index];}const char& at(size_t index)const{// 如果越界,抛出out_of_range的异常return _str[index];}//// modifyvoid push_back(char ch){*this += ch;}string& operator+=(char ch){if (_size == _capacity)reserve((size_t)_capacity*1.5 + 3);_str[_size] = ch;++_size;_str[_size] = '\0';return *this;}string& operator+=(const char* str){size_t needSpace = strlen(str);size_t leftSpace = capacity() - size();if (needSpace > leftSpace){reserve(capacity()+ needSpace);}strcat(_str, str);_size += needSpace;_str[_size] = '\0';return *this;}string& operator+=(const string& s){*this += s.c_str();return *this;}string& append(const char* str){*this += str;return *this;}string& appent(const string& s){*this += s;return *this;}string& insert(size_t pos, const string& s);string& erase(size_t pos = 0, size_t n = npos);void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}const char* c_str()const{return _str;}size_t find(char ch, size_t pos = 0)const{if (pos >= _size){return npos;}for (size_t i = pos; i < _size; ++i){if (_str[i] == ch)return i;}return npos;}size_t rfind(char c, size_t pos = npos){if (pos >= _size){pos = _size-1;}for (int i = pos; i >= 0; --i){if (_str[i] == c)return i;}return npos;}string substr(size_t pos = 0, size_t n = npos) const{// 从pos位置开始,往后借助n个字符长度if (pos >= _size){return string();}// 从pos到字符串的末尾剩余字符个数n = min(n, _size - pos);string temp(n, '\0');size_t index = 0;for (size_t i = pos; i < pos+n; ++i){temp[index++] = _str[i];}return temp;}private:char* _str;size_t _size;size_t _capacity;const static size_t npos = -1;friend ostream& operator<<(ostream& out, const string& s);};ostream& operator<<(ostream& out, const string& s){for (size_t i = 0; i < s.size(); ++i){cout << s[i];}return out;}
}int main()
{// TestMyString01();// TestMyString02();// TestMyString03();TestMyString04();_CrtDumpMemoryLeaks();return 0;
}

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

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

相关文章

携程面经1

面经 HDFS读写流程 1.读流程 客户端向NameNode发起读请求&#xff08;如果存在&#xff09;NameNode返回一批block地址客户端与第一个block的拓扑距离最近的节点建立连接以packet&#xff08;64kb&#xff09;的单位读取数据块。一个block读取完成后客户端会断开与该DataNod…

5个开源的Java项目快速开发脚手架

概览 &#xff1a; GunspigRuoYiJeecg-bootiBase4J 一、Guns 推荐指数 &#xff1a;⭐⭐⭐⭐⭐ 简介 采用主流框架 &#xff1a; 基于 Spring Boot2.0版本开发&#xff0c;并且支持 Spring Cloud Alibaba 微服务。功能齐全 &#xff1a;包含系统管理&#xff0c;代码生成&a…

这么强才给我28k,我头都不回,转身拿下40k~

时间真的过得很快&#xff0c;眨眼就从校园刚出来的帅气小伙变成了油腻大叔&#xff0c;给各位刚入道的测试朋友一点小建议&#xff0c;希望你们直通罗马吧&#xff01; 如何选择自己合适的方向 关于选择测试管理&#xff1a; 第一&#xff0c;你一定不会是一个喜欢技术&…

Vue的组件(注册、局部、组件复用、props、emit、生命周期)全解

文章目录前言知识点组件注册局部组件组件复用组件间通信props 类型检测子父组件通信之 emit动态组件生命周期函数前言 Vue 支持模块化和组件化开发&#xff0c;可以将整个页面进行模块化分割&#xff0c;低耦合高内聚&#xff0c;使得代码可以在各个地方使用。 知识点 组件注册…

accent-color一行代码,让你的表单组件变好看

不做切图仔,从关注本专栏开始 文章目录 不做切图仔,从关注本专栏开始前言兼容性语法继承性智能前言 在之前的网站开发中,我们是很难去更改的你某些控件的颜色。我们可能要使用各种技巧来自定义我们的控件。好消息是,今天如果我们想要去改变控件的颜色,css为我们提供了一些…

心系区域发展,高德用一体化出行服务平台“聚”力区域未来

交通&#xff0c;是城市的血脉。通过对人、资源、产业的连接&#xff0c;交通建设往往是城市和区域经济发展的前提。不过&#xff0c;在度过了“要想富&#xff0c;先修路”的初级建设阶段后&#xff0c;交通产业内部也出现了挑战&#xff0c;诸如城市秩序、发展成本、用户使用…

【目标检测】Dynamic Head Unifying Object Detection Heads with Attentions

文章目录一、背景二、方法2.1 scale-aware attention2.2 spatial-aware attention2.3 task-aware attention2.4 总体过程2.5 和现有的检测器适配2.6 和其他注意力机制的关联三、效果四、代码论文链接&#xff1a; https://arxiv.org/pdf/2106.08322.pdf代码链接&#xff1a;htt…

Windows 安装RocketMQ

文章目录一、RocketMQ是什么&#xff1f;二、准备工作1.环境要求2.下载与解压3.启动MQ4. 测试是否成功启动三、安装管理端1. 代码下载2. 修改配置文件3. 启动MQ客户端jar包四、rocketMQ代码的使用入门五、问题记录1. 启动mqbroker.cmd没有反应2.消费者重复消费消息一、RocketMQ…

NCRE计算机等级考试Python真题(六)

第六套试题1、算法的时间复杂度是指A.执行算法程序所需要的时间B.算法程序的长度C.算法程序中的指令条数D.算法执行过程中所需要的基本运算次数正确答案&#xff1a; D2、下列关于栈的叙述中正确的是A.在栈中只能插入数据B.在栈中只能删除数据C.栈是先进先出的线性表D.栈是先进…

【Django功能开发】如何正确使用定时任务(启动、停止)

系列文章目录 【Django开发入门】ORM的增删改查和批量操作 【Django功能开发】编写自定义manage命令 文章目录系列文章目录前言一、django定时任务二、django-apscheduler基本使用1.安装django-apscheduler2.配置settings.py的INSTALLED_APPS3.通过命令生成定时记录表3.如何创…

嵌入式 linux 系统开发网络的设置

目录 一、前言 二、linux网络静态地址设置 前言 为什么要对linux系统下的ubuntu进行网络设置呢&#xff1f; 因为我们在嵌入式开发中&#xff0c;我们要保证windows系统、linux系统、开发板的ip要处于同一个网段&#xff0c;而默认ubuntu下的linux系统的ip是动态分配的&#…

如何彻底删除SQL Server 2008中的登录账号

我个人遇到的最烦人的事情之一是 SQL Server Management Studio中“服务器名称和登录名”对话框的下拉列表。 以下是我想从 SSMS 连接屏幕中删除某些内容的两种情况: 键入的服务器名称不正确 服务器将来不需要。当我看到服务器的名称,它已经存在了很长一段时间,我知道我不会…

图像处理实战--Opencv实现人像迁移

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天来学习一下如何使用Opencv实现人像迁移&#xff0c;欢迎大家一起参与探讨交流~ 本文目录&#xff1a;一、实验要求二、实验环境三、实验原理及操作1.照片准备2.图像增强3.实现美颜功能4.背景虚化5.图像二值化处理6.人…

Day21【元宇宙的实践构想07】—— 元宇宙与人工智能

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f91e; 作者&#xff1a;那就叫我亮亮叭 &#x1f4d5; 专栏&#xff1a;元宇宙 0.0 写在前面 “元宇宙”在2021年成为时髦的概念。元宇宙到底是什么&#xff1f;元宇…

【论文笔记】Decoupling Representation and Classifier for Long-Tailed Recognition

这一篇其实并不是提出什么新的东西&#xff0c;而且是做了点类似综述的技术调用实验。省流&#xff1a;T-normalization最好用 摘要 现状&#xff1a;Existing solutions usually involve class-balancing strategies, e.g. by loss re-weighting, data re-sampling, or tran…

高燃!GitHub上标星75k+超牛的Java面试突击版

前言不论是校招还是社招都避免不了各种面试。笔试&#xff0c;如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有章可循的&#xff0c;我这个有章可循‘说的意思只是说应对技术面试是可以提前准备。运筹帷幄之后&#xff0c;决胜千里之外!不打毫无准备的仗,我觉得大…

扒系统CR8记录

目录 终极改造目标 过程记录 参考 为了将一套在线安装的系统&#xff0c;在不了解其架构、各模块细节的基础上&#xff0c;进行扒弄清楚&#xff0c;作以下记录。 终极改造目标 最终的目标&#xff0c;就是只通过CreMedia8_20230207.tar.gz解压 install 就把业务包安装了&…

安装VMWare虚拟机之后,发现网络贼卡,打开网页很慢

事情描述&#xff1a; 最近忙一个项目&#xff0c;需要到虚拟机中部署环境&#xff0c;安装完之后&#xff0c;就开整自己的项目了。 可以过几天&#xff0c;发现本地网络贼卡&#xff0c;打开各网页慢的一批&#xff0c;一开始还以为是路由器的问题&#xff0c;反复折腾之后排…

[12]云计算概念、技术与架构Thomas Erl-第5章 云使能技术

目录 第五章 云使能技术 5.1宽带网络和Internet架构 5.1.1Internet服务提供者&#xff08;ISP&#xff09; 5.1.2无连接分组&#xff08;数据报网络&#xff09; 5.1.3基于路由器的互联 5.1.4技术和商业考量 总结 5.2数据中心技术 5.2.1虚拟化 5.2.2标准化与模块化 …

微服务实战01-maven聚合工程

接下来的一段时间&#xff0c;我们将要来学习微服务&#xff0c;本着重实战的原则&#xff0c;你不需要去深究一些相关的原理&#xff0c;只要能跟着教程一步一步做下来&#xff0c;就可以快速地掌握Java微服务开发技巧。 我们学习微服务的第一步&#xff0c;就是要知道怎么创…