解决String深浅拷贝

  • 浅拷贝和深拷贝
    • 深拷贝实现
    • 写时拷贝
  • String基本功能实现

浅拷贝和深拷贝

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

深拷贝:
给每个对象独立分配资源,保证多个对象之间不会因为共享资源而造成多次释放造成程序崩溃问题

关于深浅拷贝解决方案有两种
1、深拷贝
2、引用计数拷贝+写时拷贝

深拷贝实现

传统版:

class string{public:string(const char* 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){delete[]_str;_str = new char[strlen(s._str) + 1];strcpy(_str, s._str);}return *this;}~string(){delete[] _str;_str = nullptr;}private:char* _str;};

现代版:

class string{public:string(const char* str = ""):_str(new char[strlen(str) + 1]){strcpy(_str, str);}//现代写法string (const string& s):_str(nullptr){string tmp(s._str);//构造swap(_str, tmp._str);}string& operator= (string s){swap(_str, s._str);return *this;}~string(){delete[] _str;_str = nullptr;}private:char* _str;};

写时拷贝

写时拷贝:是在浅拷贝的基础上增加了引用计数的方式来实现的,谁写谁拷贝(深拷贝)
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数计为1,每增加一个对象使用该资源,计数就+1,当某个对象销毁时,计数-1。如果计数为1时,说明该对象是资源的最后一个使用者,可以将该资源释放;否则不能释放,因为还有其他对象在使用该资源

String基本功能实现

//支持增删查改class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}const_iterator begin() const{return _str;}iterator end(){return _str + _size;}const_iterator end() const{return _str + _size;}string(const char* str = ""){_size = strlen(str);//_size最后一位留给\0_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}string(const string& s):_str(nullptr), _size(0), _capacity(0){string tmp(s._str);//构造/*  swap(_str, tmp._str);swap(_size, tmp._size);swap(_capacity, tmp._capacity);*///this->swap(tmp)swap(tmp);}string& operator= (string s){/*swap(_str, s._str);swap(_size, s._size);swap(_capacity, s._capacity);*/swap(s);return *this;}~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}//遍历//at 作用和operator[]类似,越界抛异常const char& operator[](size_t i) const// 读{assert(i < _size);return _str[i];}char& operator[](size_t i)//可读可写{assert(i < _size);return _str[i];}void reserve(size_t n)//开空间,扩展capacity{if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void resize(size_t n,char val = '\0')//开空间+初始化,扩展capacity,且初始化空间{//n < sizeif (n < _size){_size = n;_str[_size] = '\0';}else{//n > capacityif (n > _capacity){reserve(n);}// size < n < capacityfor (size_t i = _size; i < n; i++){_str[i] = val;}_str[n] = '\0';_size = n;}}void push_back(char ch){/*if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_str[_size + 1] = '\0';_size++;*/insert(_size, ch);}void append(const char* str){/*size_t len = _size + strlen(str);if (len > _capacity){reserve(len);}strcpy(_str + _size, str);_size = len;*/insert(_size, str);}string& operator += (char ch){push_back(ch);return *this;}string& operator += (const char *_str){append(_str);return *this;}//pos位置之前插入string& insert(size_t pos, const char *str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}//挪动数据char* end = _str + _size;while (end >= _str + pos){*(end + len) = *end;end--;}strncpy(_str + pos, str, len);_size += len;return *this;}string& insert(size_t pos, char ch){assert(pos <= _size);if (_size = _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}//不推荐/*int end = _size;while (end > (int)pos){_str[end - 1] = _str[end];end--;}*//*size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}*///还可以用指针char* end = _str + _size;while (end >= _str + pos){*(end + 1) = *end;end--;}_str[pos] = ch;_size++;return *this;}string& erase(size_t pos, size_t len = npos)//npos = -1{assert(pos < _size);size_t leftlen = _size - pos;//剩余的字符长度小于要删的长度if (len >= leftlen){_str[pos] = '\0';_size = pos;}else//剩余的字符长度大于要删的长度{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}size_t find(char ch, size_t pos = 0){assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;}size_t find(const char* str, size_t pos = 0){assert(pos < _size);const char* ret = strstr(_str + pos, str);if (ret){return ret - _str;}else{return npos;}}size_t size() const {return _size;}const char* c_str() const {return _str;}void clear(){_size = 0;_str[0] = '\0';}private:char* _str;size_t _size;size_t _capacity;static const size_t npos;};const size_t string::npos = -1;inline bool operator <(const string& s1, const string s2){return strcmp(s1.c_str(),s2.c_str()) < 0;}inline bool operator ==(const string& s1, const string s2){return strcmp(s1.c_str(), s2.c_str()) == 0;}inline bool operator <=(const string& s1, const string s2){return s1 < s2 || s1 == s2;}inline bool operator >(const string& s1, const string s2){return !(s1 <= s2);}inline bool operator >=(const string& s1, const string s2){return !(s1 < s2);}inline bool operator !=(const string& s1, const string s2){return !(s1 == s2);}ostream& operator <<(ostream& out, const string&s){for (auto ch : s){out << ch;}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& getline(istream& in, string& s){s.clear();char ch;ch = in.get();while (ch != '\n'){s += ch;ch = in.get();}return in;}

解决String深浅拷贝相关推荐

  1. C++---string类接口整理与深浅拷贝

    string:是表示字符串序列的类,不能操作多字节或者变长字符序列 在使用string类时,必须包含#include头文件以及using namespace std; 常见的接口整理 常见的strin ...

  2. C++ string类(包括深浅拷贝)

    目录 一.字符码表 一.为什么用string类 二.使用标准库中的string类 1.string类 2.string中的常用接口说明 (1)string类对象的常见构造 (2)string类对象访问 ...

  3. 深浅拷贝、函数、内置函数、文件处理、三元运算、递归

    深浅拷贝 import copy copy.copy() #浅拷贝 copy.deepcopy() #深拷贝 num = 110 copynum = num #赋值 一.数字和字符串 对于 数字 和 ...

  4. Python基础(三)深浅拷贝、函数、文件处理、三元运算、递归、冒泡排序

    本章内容: 深浅拷贝 函数(全局与局部变量) 内置函数 文件处理 三元运算 lambda 表达式 递归(斐波那契数列) 冒泡排序 深浅拷贝 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝 ...

  5. boolean类型_JS核心理论之《数据类型、类型转换、深浅拷贝与参数传递》

    数据类型 基本类型:共7种,也被称为值类型,是一种既非对象也无方法的数据.包括:string.number.bigint.boolean.null.undefined.symbol. 除了 null ...

  6. 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现

    浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 文章目录 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 一.什么是浅拷 ...

  7. 【C++grammar】析构、友元、拷贝构造函数、深浅拷贝

    目录 1.Destructor(析构函数) 在堆和栈(函数作用域与内嵌作用域)上分别创建Employee对象,观察析构函数的行为 2.Friend(友元) 1.为何需要友元 2.友元函数和友元类 3. ...

  8. python开发学习-day03(set集合、collection系列 、深浅拷贝、函数)

    s12-20160116-day03 pytho自动化开发 day03 Date:2016.01.16 @南非波波 课程大纲: day2 http://www.cnblogs.com/wupeiqi/ ...

  9. 9012年,当我们讨论js深浅拷贝时我们在说些什么?

    前言: 本文主要阅读对象:对深浅拷贝印象模糊对初级前端,想对js深浅拷贝聊一聊的中级前端.如果是对这些有完整对认知体系和解决方法的大佬,可以选择略过. 复制代码 正文: 讨论深浅拷贝,首先要从js的基 ...

最新文章

  1. 15个应该掌握的jupyter notebook技巧
  2. 监控录像帮忙找回医院被偷的女婴
  3. 10、如何查看MySQL系统帮助?
  4. QT安卓web使用mysql_Qt使用MySQL笔记一
  5. numpy找到矩阵中不同元素的种类_基于NumPy和图像分类的人工神经网络构建
  6. AccuREST Stub Runner发布
  7. [libuv] libuv安装
  8. 【资源下载】512页IBM沃森研究员Charu最新2018著作《神经网络与深度学习》(附下载链接)
  9. linux基本使用(一)
  10. 【BZOJ4837】LRU算法 [模拟]
  11. 每天定时自动备份docker的mysql
  12. 辽宁计算机专业大学排名及分数线,辽宁一本大学排名及分数线2021
  13. linux安装硬盘阵列卡驱动,centos7 RAID磁盘阵列卡驱动安装图文教程
  14. 区块链电子合同铸就数字经济信任基石
  15. 2016年,续航新能量
  16. 浅谈SVG的两个黑魔法
  17. 程序员职场小白修炼记1——安晓辉《解忧程序员》读书笔记
  18. Java中的门面设计模式
  19. 在金融行业中,直播获客应该怎么做呢?
  20. Linux基础--存储管理(逻辑卷lvm,swap交换分区,mount,raid磁盘阵列)

热门文章

  1. 自助建站系统一般一年多少钱?
  2. puppeteer调研--生成页面的屏幕截图和PDF
  3. golang的logrus取消标准输出
  4. elementary安装Java,使用U盘安装Linux最美桌面发行版Elementary OS 及常用开发环境配置(JDK,Redis,MySQL,Docker,IDEA,STS)...
  5. 制作自已的Linux操作系统ISO
  6. android虚拟应用沙箱,基于虚拟化及重定向技术的Android沙箱设计与实现
  7. Android 中的内存泄漏和内存溢出
  8. pycharm如何添加文件注释和函数注释
  9. java static方法(单例)
  10. eclipse的PHP插件安装