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

c++ string类的模拟实现的注意事项

一.构造函数

第一种形式,使用字符指针赋值

为了防止修改,我们传入了常量字符串。但是这里的初始化列表出错了,因为_str是一个变量,将常量给到一个变量涉及到权限的放大,是错误的。那该怎么写呢?对_str的赋值只能使用strcpy字符串拷贝,如下:

这样对了吗??还是不对!!!因为_str没有开辟空间!!!!

体现了初始化列表与函数的结合

但是,main函数中创建一个字符串对象却出错了!!!!

为什么呢?注意初始化列表的顺序!!!!!是按照变量定义的顺序进行的!!!然而_str是最先定义的,所以在执行_str(new char[_chpacity+1]时,_capacity还是随机值(或者是vs下的0),所以就会出错!!!。所以,对_str的空间的开辟最好定义在函数体内,如下:

二.头文件包含问题以及预处理文件的查看

上面我们在写mystring.h的时候没有包含任何头文件,但为什么strcpy能够使用,能够编译运行通过呢?

这是因为,十以上如处理后的文件是将main所在文件中包含的头文件都展开了,也就是将iostream、string、std、mystring.h依次展开,所以当mystring.h中用到strcpy时,他就会主动去上面寻找定义。这可以根据预处理的文件证明。如下为查看预处理文件的方式:

右键项目-属性-c\c++-预处理器,进行如下修改:

找到要查看的文件的预处理文件,进行编译:

打开被编译文件所在文件夹:

找到debug文件夹:

进入debug文件夹并打开test1.i文件:

就可以看到了:

在main函数之上都是头文件的展开,包括了库里的头文件以及我们自己写的头文件。

注意,看完了记住将是改成否!!!

但注意,如果mystring.h的包含实在std上面的话,有些std中的东西在mystring.h中就用不了了,比如cout。

三.c_str

注意,返回值是常量指针类型。

四.无参构造

能否再写个如下的无参构造?

不可以,这样的话,c_str可能会崩掉。

那怎么写最好呢?只写一个构造函数,并且是全缺省的,如下:

五.赋值重载

如果没有重写赋值函数,就会出现下面的情况:

进行了浅拷贝,s和s2指向了同一块空间。所以要重写赋值重载函数:

六.operator[]

两个版本,可读可写。

七.迭代器

然后再写个const形式的:

这样对吗?显然不对

为什么呢?因为const iterator其实是等价于char* const,也就是说表示指针是一个常量的,他的指向不能修改,但是,他指向的空间的内容可以修改!!!,那就没有防止修改的意义了。应该如下修改

这样就会发现,const字符串调用了begin后,生成的迭代器不能给到一个变量,而只能给到一个常量迭代器。,这样,const字符串就不能被修改了。

八.push_back

if里面的内容其实就是reserve预留空间这个函数,所以我们可以封装起来:

但注意细节,将tmp给到_str前,要释放原来的空间:注意是显示放再赋值

还有一个错误:尾插后要让size加一,并且要在尾部添加‘\0'。,最后如下:

九.append

注意最后一个字符置为0,以防传参时仅仅传入一个字符的地址!!!

十.insert

这样写有一个弊端:向后移动的时候,字符串末尾的'\0'被覆盖了!!!怎么办??一种方式是在插入完毕后再规定_size位置为\0,还有一种方法是从第_size位置开始移动,也就是连着末尾的\0一起移动,如下:

这段代码还有要注意的地方:如果移动的代码是像下面一样写的,那么当头插的时候,由于i是size_t类型,i减到最后本应是-1,但是编译器认为这是无符号整型,是一个非常大的数,就会导致无限循环:

一定要注意细节。

十一.流插入重载

第一种方式,写成友元函数。但要注意,友元函数必须和对应的类写在一个命名空间中!!!!否则依然无法访问类中的私有成员,如下:

但其实,这里的流插入不需要访问类内部的私有成员,所以不是非得写成友元函数,也可以在明明空间外面这样写:

注意,参数有误,写到命名空间外面后,就要在string前面加上命名空间的名字,如下:

注意,这里的auto其实就是转成了迭代器的调用。那么它调用的是const迭代器还是非const迭代器呢?如下可以证明

调用的是常量迭代器

十二.流提取重载

注意,有个问题,cin会自动跳过空格,去获取下一个字符。这怎么办??

cin是istream类型的对象,其中有一个成员函数get,它可以拿到所有的字符

还有一个问题,输入流是要把s的内容全部改了,但是加等就是简简单单的追加。所以在操作之前要将s清空。如下加上这个clear函数:

但是这个流提取的写法还不够好,它得一直扩容。

解决方法一:使用reserve预留空间。但是,不知道需要多大,太大了浪费

解法二:使用一个字符数组:

十三.erase

这其实只是一个最主要步骤。但是还有其他的。首先,npos是自定义的,要定义成成员变量,为了防止修改,将他定义成const的,同时,npos应该是所有成员共享的,所以定义成static的。static成员要在类外初始化

其次,还要考虑pos+len>size的情况

最后,别忘记更新_size的值。

十四.拷贝构造

开辟一个一样大的空间,将数据拷贝过去。

深拷贝到本质:不能任由指针成员进行拷贝,但我们可以考虑让别人做

也可以封装成函数,注意命名空间

十五.回看赋值重载

可以调用reserve来开辟空间。

但也可以用到swap,借他人之手来进行

这种现代写法有个好处,原先自己的空间不用去主动释放,而是交换给了tmp,让tmp去释放。

最极致的现代写法:

直接交换s,但注意,一定要改成string变量,而不能使用const引用了

相关文章:

c++ string类的模拟实现的注意事项

一.构造函数 第一种形式,使用字符指针赋值 为了防止修改,我们传入了常量字符串。但是这里的初始化列表出错了,因为_str是一个变量,将常量给到一个变量涉及到权限的放大,是错误的。那该怎么写呢?对_str的赋…...

Unity3D中控制3D场景中游戏对象显示层级的详解

前言 在Unity3D开发中,控制游戏对象的显示层级(也称为渲染顺序或渲染层级)是一个常见的需求,特别是在处理复杂的3D场景时,如角色、道具、UI元素等的可见性和渲染顺序的管理变得尤为重要。Unity通过几种不同的机制来实…...

代码执行漏洞-Log4j2漏洞 vulhub CVE-2021-44228

步骤一:执行以下命令启动靶场环境并在浏览器访问!!! 查看端口 浏览器访问 可以发现 /solr/admin/cores?action 这⾥有个参数可以传,可以按照上⾯的原理 先构造⼀个请求传过去存在JNDI注⼊那么ldap服务端会执⾏我们传上去的payload JDNI项⽬地址 https://github.com…...

uniapp / uniapp x UI 组件库推荐大全

在 uniapp 开发中,我们大多数都会使用到第三方UI 组件库,提起 uniapp 的UI组件库,我们最常使用的应该就是uview了吧,但是随着日益增长的需求,uview 在某些情况下已经不在满足于我们的一些开发需求,尽管它目…...

花8000元去培训机构学习网络安全值得吗,学成后就业前景如何?

我就是从培训机构学的网络安全,线下五六个月,当时学费不到一万,目前已成功入行。所以,只要你下决心要入这一行,过程中能好好学,那这8000就花得值~ 因为只要学得好,工作两个多月就能赚回学费&am…...

PhpStorm 下调试功能配置

调试是开发过程中的关键环节,能够极大地减少应用程序中的错误并提高代码质量。PhpStorm 作为一款功能强大的 IDE,提供了丰富的调试功能,结合 Xdebug,可以让开发者更轻松地进行 PHP 应用程序的调试。本指南将详细介绍如何在 PhpSto…...

MVC(Model-View-Controller)和MVVM(Model-View-ViewModel)

1、MVC MVC(Model-View-Controller) 是一种常用的架构模式,用于分离应用程序的逻辑、数据和展示。它通过三个核心组件(模型、视图和控制器)将应用程序的业务逻辑与用户界面隔离,促进代码的可维护性、可扩展…...

【H2O2|全栈】关于HTML(4)HTML基础(三)

HTML相关知识 目录 HTML相关知识 前言 准备工作 标签的具体分类(三) 本文中的标签在什么位置中使用? 列表 ​编辑​编辑 有序列表 无序列表 自定义列表 表格 拓展案例 预告和回顾 后话 前言 本系列博客将分享HTML相关知识点…...

关于找不到插件 ‘org.springframework.boot:spring-boot-maven-plugin:‘的解决方案

找到项目结构后,点击库,全选所有后点击应用即可...

深入RabbitMQ世界:探索3种队列、4种交换机、7大工作模式及常见概念

文章目录 文章导图RabbitMQ架构及相关概念四大核心概念名词解读 七大工作模式及四大交换机类型0、前置了解-默认交换机DirectExchange1、简单模式(Simple Queue)-默认DirectExchange2、 工作队列模式(Work Queues)-默认DirectExchange3、发布/订阅模式(Publish/Subscribe)-Fano…...

将目标检测模型导出到C++|RT-DETR、YOLO-NAS、YOLOv10、YOLOv9、YOLOv8

点击下方卡片,关注“小白玩转Python”公众号 最近,出现了更新的YOLO模型,还有RT-DETR模型,这是一个声称能击败YOLO模型的变换器模型,我想将这些模型导出并进行比较,并将它们添加到我的库中。在这篇文章中&a…...

【Windows】解决新版 Edge 浏览器开机自启问题(简单有效)

文章目录 1.前言2.查找资料3.查找方法4.解决办法1.点击浏览器的三个...,然后点击设置2.选择【开始、主页和新建标签页】选项卡,然后关闭【Windows设备启动时】 结语 参考文章: 解决新版 Edge 浏览器开机自启问题(简单有效&#xf…...

如何给3D人物换衣服CC4

1.导入人物 2.设置人物Apose 3.导入衣服 create -> accessory 选择fbx文件 设置衣服的大小和位置。 4.绑定衣服 设置衣服的权重 添加动作就可以看效果了。...

如何对列表、字符串进行分组

如何对列表、字符串进行分组 1、效果 2、代码 使用python自带库collections中的Counter函数即可实现 代码如下: # -*- coding: utf-8 -*-""" @contact: @file: test.py @time: 2024/9/8 11:18 @author: LDC """ from collections import Co…...

【GEE代码实例教程详解:NDVI时间序列趋势分析】

GEE(Google Earth Engine)是一个强大的云计算平台,用于处理和分析大规模地球科学数据集。以下是一个关于如何使用GEE进行NDVI(归一化植被指数)时间序列趋势分析的详细教程。 一、引言 NDVI时间序列趋势分析是一种统计…...

51单片机-DS1302(RTC实时时钟芯片)

数据手册在主页资源免费贡献 开发板芯片数据手册 https://www.alipan.com/s/nnkdHhMGjrz 提取码: 95ik 点击链接保存,...

FreeRTOS学习笔记—②RTOS的认识及任务管理篇

由于正在学习韦东山老师的RTOS课程,结合了网上的一些资料,整理记录了下自己的感悟,用于以后自己的回顾。如有不对的地方请各位大佬纠正。 文章目录 一、RTOS的优势二、RTOS的核心功能2.1 任务管理2.1.1 任务的创建2.1.2 任务的删除*2.1.3 任…...

【C++从练气到飞升】22---C++中的异常

🎈个人主页:库库的里昂 ✨收录专栏:C从练气到飞升 🎉鸟欲高飞先振翅,人求上进先读书🎉 目录 ⛳️推荐 一、C语言传统的处理错误的方式 二、C异常 三、异常的使用 3.1 异常的抛出和捕获 3.1.1 异常的抛…...

前端:HTML、CSS、JS、Vue

1 前端 内容概要 了解前端三件套(HTML、CSS、JS)在前端所起的作用掌握HTML标签的功能,掌握重要标签(a标签,form标签)了解CSS了解JS的基础语法掌握Vue的基础语法重点掌握Vue项目怎么启动项目掌握前后端分离是什么。前端做什么事情,后端做什么…...

RocksDB简介

一、RocksDB是什么 常见的数据库如 Redis Mysql Mongo 可以单独提供网络服务RocksDB提供存储服务,是一个嵌入式KV存储引擎 Rocksdb没有server code,用户需要自己实现server的部分来得到c-s架构的数据库。二、RocksDB的诞生 基于flash存储和ssd普及,网络latency在query worklo…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

大数据学习(132)-HIve数据分析

​​​​🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言&#x1f4…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...