string(模拟实现与深拷贝)

news2024/12/24 22:11:33

目录

深拷贝与浅拷贝

浅拷贝:

深拷贝

写时拷贝(了解)

模拟实现

准备

完整代码 


深拷贝与浅拷贝

浅拷贝:

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

就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一不想分享就你争我夺,玩具损坏。
可以采用深拷贝解决浅拷贝问题,即: 每个对象都有一份独立的资源,不要和其他对象共享 。父母给每个孩子都买一份玩具,各自玩各自的就不会有问题了

深拷贝

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

 

写时拷贝(了解)

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成 1 ,每增加一个对象使用该资源,就给计数增加1 ,当某个对象被销毁时,先给该计数减 1 ,然后再检查是否需要释放资源,如果计数为 1 ,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。

模拟实现

准备

namespace frog

{

  class string

  {

  public:

    typedef char* iterator;

  public:

    string(const char* str = "");

    string(const string& s);

    string& operator=(const string &s);

    ~string();

    //

    // iterator

    iterator begin();

    iterator end();

    /

    // modify

    void push_back(char c);

    string& operator+=(char c);

    void append(const char* str);

    string& operator+=(const char* str);

    void clear();

    void swap(string& s);

    const char* c_str()const;

    /

    // capacity

    size_t size()const

    size_t capacity()const

    bool empty()const

    void resize(size_t n, char c = '\0');

    void reserve(size_t n);

    /

    // access

    char& operator[](size_t index);

    const char& operator[](size_t index)const;

    /

    //relational operators

    bool operator<(const string& s);

    bool operator<=(const string& s);

    bool operator>(const string& s);

    bool operator>=(const string& s);

    bool operator==(const string& s);

    bool operator!=(const string& s);

    // 返回c在string中第一次出现的位置

    size_t find (char c, size_t pos = 0) const;

    // 返回子串s在string中第一次出现的位置

    size_t find (const char* s, size_t pos = 0) const;

    // 在pos位置上插入字符c/字符串str,并返回该字符的位置

    string& insert(size_t pos, char c);

    string& insert(size_t pos, const char* str);

     

    // 删除pos位置上的元素,并返回该元素的下一个位置

    string& erase(size_t pos, size_t len);

  private:

    char* _str;

    size_t _capacity;

    size_t _size;

  }

};

完整代码 

#pragma once
#include<iostream>
#include<string>
#include<assert.h>
namespace bit

{

    class string
    {

    public:

        typedef char* iterator;
		typedef char* iterator;
		typedef const char* const_iterator;


    public:

        string(const char* str = "")
            :_size(strlen(str))
            , _capacity(_size)
        {
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }

        string(const string& s)
        {
        	_str = new char[s._capacity+1];
        	strcpy(_str, s._str);
        	_size = s._size;
        	_capacity = s._capacity;
        }
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

		const_iterator end() const
		{
			return _str + _size;
		}


        string& operator=(const string& s)
        {
            if (this != &s)
            {
                char* tmp = new char[s._capacity + 1];
                strcpy(tmp, s._str);

                delete[] _str;
                _str = tmp;
                _size = s._size;
                _capacity = s._capacity;
            }
        }

            ~string()
            {
                delete[] _str;
                _str = nullptr;
                _size = _capacity = 0;
            }
			void swap(string& s)
			{
				std::swap(_str, s._str);
				std::swap(_size, s._size);
				std::swap(_capacity, s._capacity);
			}

			
			
			
			string& operator=(string tmp)
			{
				swap(tmp);

				return *this;
			}

			

			char& operator[](size_t pos)
			{
				assert(pos < _size);

				return _str[pos];
			}

			const char& operator[](size_t pos) const
			{
				assert(pos < _size);

				return _str[pos];
			}

			size_t capacity() const
			{
				return _capacity;
			}

			size_t size() const
			{
				return _size;
			}

			const char* c_str() const
			{
				return _str;
			}

			void reserve(size_t n)
			{
				if (n > _capacity)
				{
					char* tmp = new char[n + 1];
					strcpy(tmp, _str);
					delete[] _str;
					_str = tmp;

					_capacity = n;
				}
			}

			void resize(size_t n, char ch = '\0')
			{
				if (n <= _size)
				{
					_str[n] = '\0';
					_size = n;
				}
				else
				{
					reserve(n);
					while (_size < n)
					{
						_str[_size] = ch;
						++_size;
					}

					_str[_size] = '\0';
				}
			}

			size_t find(char ch, size_t pos = 0)
			{
				for (size_t i = pos; i < _size; i++)
				{
					if (_str[i] == ch)
					{
						return i;
					}
				}

				return npos;
			}

			size_t find(const char* sub, size_t pos = 0)
			{
				const char* p = strstr(_str + pos, sub);
				if (p)
				{
					return p - _str;
				}
				else
				{
					return npos;
				}
			}

			string substr(size_t pos, size_t len = npos)
			{
				string s;
				size_t end = pos + len;
				if (len == npos || pos + len >= _size) 
				{
					len = _size - pos;
					end = _size;
				}

				s.reserve(len);
				for (size_t i = pos; i < end; i++)
				{
					s += _str[i];
				}

				return s;
			}

			void push_back(char ch)
			{
				if (_size == _capacity)
				{
					reserve(_capacity == 0 ? 4 : _capacity * 2);
				}

				_str[_size] = ch;
				++_size;
				_str[_size] = '\0';
			}

			void append(const char* str)
			{
				size_t len = strlen(str);
				if (_size + len > _capacity)
				{
					reserve(_size + len);
				}

				strcpy(_str + _size, str);
				_size += len;
			}

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

			string& operator+=(const char* str)
			{
				append(str);
				return *this;
			}

			
			void insert(size_t pos, char ch)
			{
				assert(pos <= _size);
				if (_size == _capacity)
				{
					reserve(_capacity == 0 ? 4 : _capacity * 2);
				}

				// 17:17
				size_t end = _size + 1;
				while (end > pos)
				{
					_str[end] = _str[end - 1];
					--end;
				}

				_str[pos] = ch;
				_size++;
			}

			void insert(size_t pos, const char* str)
			{
				assert(pos <= _size);

				size_t len = strlen(str);
				if (_size + len > _capacity)
				{
					reserve(_size + len);
				}

				// 挪动数据
				int end = _size;
				while (end >= (int)pos)
				{
					_str[end + len] = _str[end];
					--end;
				}

				strncpy(_str + pos, str, len);
				_size += len;
			}

			void erase(size_t pos, size_t len = npos)
			{
				assert(pos < _size);

				if (len == npos || pos + len >= _size)
				{
					_str[pos] = '\0';
					_size = pos;
				}
				else
				{
					size_t begin = pos + len;
					while (begin <= _size)
					{
						_str[begin - len] = _str[begin];
						++begin;
					}
					_size -= len;
				}
			}

			bool operator<(const string& s) const
			{
				return strcmp(_str, s._str) < 0;
			}

			bool operator==(const string& s) const
			{
				return strcmp(_str, s._str) == 0;
			}

			bool operator<=(const string& s) const
			{
				return *this < s || *this == s;
			}

			bool operator>(const string& s) const
			{
				return !(*this <= s);
			}

			bool operator>=(const string& s) const
			{
				return !(*this < s);
			}

			bool operator!=(const string& s) const
			{
				return !(*this == s);
			}

			void clear()
			{
				_str[0] = '\0';
				_size = 0;
			}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;

		
	public:
		const static size_t npos;
	};

	const size_t string::npos = -1;

	

}

	

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

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

相关文章

AMSET计算极化声子频率

前面已有文章介绍过amset这个软件&#xff0c;包括形变势VASPAMSET计算形变势、迁移率散射AMSET计算不同散射机制下载流子迁移率的计算和绘制功能中能带结构VASPAMSET plot 绘制能带图的使用。 同时&#xff0c;通过amset可以处理密度泛函微扰计算&#xff08;DFPT&#xff09;…

软件产品鉴定测试需要哪些材料?选择第三方软件检测机构的必要性

在当今数字化时代&#xff0c;软件产品无论是在企业还是个人生活中都扮演着重要的角色。然而&#xff0c;随着软件产品的不断增多和市场竞争的加剧&#xff0c;软件产品进行鉴定测试显得尤为重要。 一、软件鉴定测试需要提供哪些材料? 1、软件产品的版本号和更新说明 2、软…

2023国赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

docker容器的基础操作

一、安装docker服务&#xff0c;配置镜像加速器 1.安装必要的一些系统工具 2.添加软件源信息 3.更新源并安装 Docker-ce 4.安装校验 [rootnode ~]# docker version 5.docker镜像加速 可以在阿里云的容器镜像服务中查看配置镜像加速器 二、下载系统镜像&#xff08;Ubuntu、 …

AUTOSAR规范与ECU软件开发(实践篇)5.1 ETAS ISOLAR-A工具简介

前言 如前所述, 开发者可以先在系统级设计工具ISOLAR-A中设计软件组件框架, 包括端口接口、 端口等, 即创建各软件组件arxml描述性文件; 再将这些软件组件描述性文件导入到行为建模工具, 如Matlab/Simulink中完成内部行为建模。 亦可以先在行为建模工具中完成逻辑建模, 再…

【ES6】—数组的扩展

一、类数组/ 伪数组 1. 类/伪数组: 并不是真正意义的数组&#xff0c;有长度的属性&#xff0c;但无法使用Array原型上的方法 let divs document.getElementsByTagName(div) console.log(divs) // HTMLCollection []let divs2 document.getElementsByClassName("xxx&q…

C++ malloc/free/new/delete详解(内存管理)

C malloc/free/new/delete详解&#xff08;内存管理&#xff09; malloc/free典型用法内存分配实现过程brk和mmap申请小于128k的内存申请大于128k的内存释放内存brk和mmap的区别 new/delete典型用法 内存分配实现过程new/delete和malloc/free的区别malloc对于给每个进程分配的内…

【matlab利用shp文件制作mask白化文件】

matlab白化文件 mask文件的作用matlab制作mask文件mask结果 mask文件的作用 地理信息绘图中的 “mask” 通常指的是遮罩或掩膜&#xff0c;用于在地图或图像上隐藏、高亮或标记特定区域。 数据可视化&#xff1a; 地理信息绘图 mask 可以用于突出显示特定地理区域&#xff0c;使…

第四讲:Bean的生命周期

Bean的生命周期 一、生命周期演示二、添加Bean后置处理器 简单的描述并测试Bean的生命周期&#xff08;细节会在后续文章中单独讲解&#xff09;&#xff0c;并加入一些BeanPostPorcessor处理测试。 一、生命周期演示 准备一个普通的SpringBoot项目 import lombok.extern.slf…

CentOS7安装部署Doris

文章目录 CentOS7安装部署Doris一、前言1.简介2.环境 二、正文1.Doris基础1&#xff09;架构图2&#xff09;通讯端口 2.部署服务器3.安装基础环境1&#xff09;安装JDK 112&#xff09;安装GCC3&#xff09;设置文件句柄数4&#xff09;关闭交换分区&#xff08;swap&#xff…

python 打印一个条形堆积图

背景 今天介绍一个不使用 matplot&#xff0c;通过 DebugInfo模块打印条形堆积图 的方法。 引入模块 pip install DebugInfo打印销售转化数据 下面的代码构建了两个销售团队&#xff0c;团队A 和团队B&#xff1b;两个团队的销售数据构成了公司总的销售成果。以条形堆积图的…

不同屏幕的触控技术

不同显示屏的触控技术原理有所不同。触摸屏的基本原理是&#xff0c;用手指或其他物体触摸安装在显示器前端的触摸屏时&#xff0c;所触摸的位置(以坐标形式)由触摸屏控制器检测&#xff0c;并通过接口(如RS-232串行口)送到CPU&#xff0c;从而确定输入的信息。 目前市场上常…

机器学习之数据清洗

一、介绍 数据清洗是机器学习中的一个重要步骤&#xff0c;它涉及对原始数据进行预处理和修复&#xff0c;以使数据适用于机器学习算法的训练和分析。数据清洗的目标是处理数据中的噪声、缺失值、异常值和不一致性等问题&#xff0c;以提高数据的质量和准确性。 二、方法 处理…

电动汽车智能充电桩及运营管理云解决方案-安科瑞黄安南

摘要&#xff1a;电动汽车采用了电力作为发动能源&#xff0c;但是同样存在很大缺陷,即续航能力方面存在较大不足。因此如何利用现代技术进行电动汽车的智 能充电便十分重要。在电动汽车智能充 电的研究过程中需要用到的技术有有电力电子 变流技术、REIP无线射频技术、智能监控…

Java代码审计13之URLDNS链

文章目录 1、简介urldns链2、hashmap与url类的分析2.1、Hashmap类readObject方法的跟进2.2、URL类hashcode方法的跟进2.3、InetAddress类的getByName方法 3、整个链路的分析3.1、整理上述的思路3.2、一些疑问的测试3.3、hashmap的put方法分析3.4、反射3.5、整个代码 4、补充说明…

node_modules.cache是什么东西

一开始没明白这是啥玩意&#xff0c;还以为是npm的属性&#xff0c;网上也没说过具体的来源出处 .cache文件的产生是由webpack4的插件cache-loader生成的&#xff0c;node_modules里下载了cache-loader插件&#xff0c;很多朋友都是vuecli工具生成的项目&#xff0c;内置了这部…

贝锐蒲公英助力建设工程咨询企业,高效安全远程访问数据档案库

随着数字信息化进程的加深&#xff0c;数字化转型已成为企业实现业务流程自动化、提高工作效率、降低成本和提高用户满意度的重要手段。其中&#xff0c;档案工作的标准化、规范化是信息化建设的前提和必要条件&#xff0c;对于建设工程咨询企业而言&#xff0c;一个完善的数字…

【数据结构与算法】迪杰斯特拉算法

迪杰斯特拉算法 介绍 迪杰斯特拉&#xff08;Dijkstra&#xff09;算法是典型最短路径算法&#xff0c;用于计算一个节点到其他节点的最短路径。它的主要特点是以中心向外层层扩展&#xff08;广度优先搜索思想&#xff09;&#xff0c;直到扩展到终点为止。 算法过程 设置…

小米AI音箱联网升级折腾记录(解决配网失败+升级失败等问题)

小米AI音箱&#xff08;一代&#xff09;联网升级折腾记录 我折腾了半天终于勉强能进入下载升级包这步&#xff0c;算是成功一半吧… 总结就是&#xff0c;网络信号一定要好&#xff0c;需要不停换网找到兼容的网&#xff0c;还需要仔细配置DNS让音响连的上api.mina.mi.com 推荐…

JavaWeb-特殊文件(propertis与XML)

目录 Properties文件 一.properties介绍 二.properties使用 三.解决中文乱码问题 XML文件 一.XML介绍 二.XML文件的语法规则 三.XML的使用 Properties文件 一.properties介绍 1.什么是properties文件 Properties文件是一种常用的配置文件格式&#xff0c;用于存储键值…