关键词:
由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃。
实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数。
由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间。这种方法就是写时拷贝。
在构造函数中开辟新的空间时多开辟4个字节的空间,用来存放引用计数器,记录这快空间的引用次数。
- #include<iostream>
- #include<stdlib.h>
- using namespace std;
- class String
- {
- public:
- String(char *str = "")
- :_str(new char[strlen(str) + 5])
- {
- *(int *)_str = 1;
- _str += 4;
- strcpy(_str, str);
- }
- ~String()
- {
- if (_str != NULL)
- {
- _Release();
- }
- }
- String(const String& str)
- {
- _str = str._str;
- ++_GetRefCount();
- }
- String& operator=(const String& str)
- {
- if (this != &str)
- {
- _Release();
- _str = str._str;
- ++ _GetRefCount();
- }
- return *this;
- }
- char& operator[](int index)//写时拷贝
- {
- if (_GetRefCount()>1)//当引用次数大于1时新开辟内存空间
- {
- --_GetRefCount();//原来得空间引用计数器减1
- char *str = new char[strlen(_str) + 5];
- strcpy(str+4, _str);
- _str = str+4;
- _GetRefCount()++;
- }
- return _str[index];
- }
- friend ostream& operator<<(ostream& output, const String& str)
- {
- output << str._str;
- return output;
- }
- private:
- int& _GetRefCount()
- {
- return *(int *)(_str - 4);
- }
- void _Release()
- {
- if (--_GetRefCount() == 0)
- {
- delete[] (_str-4);
- }
- }
- private:
- char *_str;
- };
==============》
将_pCount与_str所指向的空间放在一起,即只用new开辟一次空间
class String { friend ostream& operator<<(ostream& os,String& s); public: String(const char*str = "") :_str(new char[strlen(str)+1+4]) { *(int *)_str = 1; //*_pCount = 1 _str = _str+4; //找到数据存放的位置 strcpy(_str,str); GetCount() = 1; } String(const String& str) :_str(str._str) { ++GetCount(); } ~String() { if(--GetCount() == 0) { delete[] (_str-4); } } String& operator=(const String& s) { if (this != &s) { if (--GetCount() == 0) { delete[] (_str-4); } ++GetCount(); _str = s._str; } return *this; } private: int& GetCount() //获得_pCount { return *((int *)_str-1); } private: char *_str; }; ostream& operator<<(ostream& os,String& s) { os<<s._str; return os; }
void test1() { String str1("abcde"); String str2(str1); String str3; str3 = str2; cout<<str1<<endl; cout<<str2<<endl; cout<<str3<<endl; }
string类的写时拷贝与引用计数(代码片段)
...数时导致一块内存被多次释放,导致程序奔溃。实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数。由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就... 查看详情
string类的深浅拷贝,写时拷贝
string类的深浅拷贝,写时拷贝浅拷贝:多个指针指向同一块空间,多次析构同一块内存空间,系统会崩溃。(浅拷贝就是值拷贝)深拷贝:给指针开辟新的空间,把内容拷贝进去,每个指针都指向自己的内存空间,析构时不会内... 查看详情
string类的实现写时拷贝浅析
由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间。这种方法就是写时拷贝。这... 查看详情
c++深浅拷贝写时拷贝(代码片段)
前言:本章以string类为例介绍浅拷贝与深拷贝,引用计数写时拷贝作为了解内容,string类的模拟实现参考C++string类的模拟实现。文章目录1.浅拷贝2.深拷贝3.引用计数+写时拷贝1.浅拷贝浅拷贝:对于有申请... 查看详情
c语言如何获得变量的物理地址以及简单的写时拷贝测试
基本的思路:linux下的/proc/self是对自身进程映射的文件夹,里面的pagemap允许查看到每个虚拟页映射到的物理页。#include<stdio.h>#include<unistd.h>#include<inttypes.h>intptr_tMytop(uintptr_tvaddr)FILE*pagemap;intptr_ 查看详情
探秘写时拷贝的真相发布啦!
...们对写时拷贝并不陌生,Linuxfork和STLstring是比较典型的写时拷贝应用,本文只讨论 查看详情
深拷贝&浅拷贝&引用计数&写时拷贝
(1).浅拷贝:classString{public:String(constchar*str=""):_str(newchar[strlen(str)+1]){strcpy(_str,str);}~String(){if(NULL!=_str){delete[]_str;_str=NULL;}}private:char*_str;};intmain(){Strings1("hello");Str 查看详情
c++——浅拷贝深拷贝写时拷贝详解(代码片段)
...决浅拷贝的问题——引用计数写时拷贝浅拷贝与深拷贝用String类模拟用将“/0”拷贝进去:调用系统默认的拷贝构造函数,结果就是内容相同,地址相同。说明这个方法是浅拷贝方法。浅拷贝方法带来的问题就是同一... 查看详情
c++从青铜到王者第八篇:stl之string类的模拟实现(代码片段)
系列文章目录文章目录系列文章目录前言一、string类的模拟实现1.经典的string类问题2.浅拷贝3.深拷贝4.传统版的string类5.现代版的string类6.写时拷贝(了解)7.string类的模拟实现总结前言一、string类的模拟实现1.经典的string类问题上篇... 查看详情
写时拷贝(copyonwrite)(代码片段)
适用于深拷贝提高效率的一种方法。 例如string类,在拷贝构造时,会要用到深拷贝。如果用浅拷贝,会导致两对象的指针指向同一块空间,导致对象析构时,导致同一块空间释放两次,程序奔... 查看详情
带有 APFS 的 macOS:终端中的写时复制
】带有APFS的macOS:终端中的写时复制【英文标题】:macOSwithAPFS:Copy-On-WriteinTerminal【发布时间】:2020-04-1205:34:02【问题描述】:我正在编写一些将备份数据组合到一个目录中的小脚本。然后将目录内容上传到云服务,然后我们可... 查看详情
c++初阶string底层框架模拟实现(代码片段)
...贝优缺点1.浅拷贝2.深拷贝3.深拷贝现代版4.写时拷贝三、string框架搭建1.框架定义2.构造函数3.析构函数4.赋值重载5.实现扩容6.增添数据7.删除数据8.数据查找9.iterator迭代器10.插入/提取流与getline函数四.完整代码一、前言本节文章... 查看详情
c++初阶string底层框架模拟实现(代码片段)
...贝优缺点1.浅拷贝2.深拷贝3.深拷贝现代版4.写时拷贝三、string框架搭建1.框架定义2.构造函数3.析构函数4.赋值重载5.实现扩容6.增添数据7.删除数据8.数据查找9.iterator迭代器10.插入/提取流与getline函数四.完整代码一、前言本节文章... 查看详情
Swift 如何实现 Array 的写时复制行为?
】Swift如何实现Array的写时复制行为?【英文标题】:HowSwiftimplementArray\'scopy-on-writebehavior?【发布时间】:2016-04-0803:27:18【问题描述】:看完buildbetterappswithvaluetype。在他们制作的Photoshop示例中,他们说在该图表的两个实例中唯一... 查看详情
fork()的写时复制技术(转载)
本文转载自http://www.cnblogs.com/wuchanming/p/4495479.html,为了方便以后查看。。。写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork( )系统调用时,内核原样复制父进程的整个地址空间并把复制的... 查看详情
写时拷贝技术
CopyOnWrite(COW):写时拷贝技术一、什么是写时拷贝技术:写时拷贝技术可以理解为“写的时候才去分配空间”,这实际上是一种拖延战术。举个栗子:650)this.width=650;"src="http://img.blog.csdn.net/20160829170427832?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkb... 查看详情
再谈qvector与qbytearray——qt的写时复制(copyonwrite)技术(代码片段)
...和赋值方面的一点东西,今天接着从QVector展开谈谈Qt的写时复制技术。老实说,“隐式共享,引用计数,写时复制”也是老调重弹的话题了,不过也是QTL与ST 查看详情
手撕stlstring类(代码片段)
string类标准库中的string类string类string类的常用接口说明string类的模拟实现Memberfunctions构造函数析构函数拷贝构造(深拷贝)赋值重载(深赋值)CapacitysizecapacityreserveresizeclearModifierspush_backappendinsertoperator+=swape... 查看详情