浅析深拷贝之写时拷贝&引用计数
来源:互联网 发布:淘宝下载电脑版 编辑:程序博客网 时间:2024/05/18 02:11
写时拷贝&引用计数–浅析深拷贝的另一种实现方式
深拷贝在重复内容条件下的高成本情况分析
以模拟实现一个简单的String类为例,我们知道对每个对象申请的字符串的空间应相互独立
即 在实现拷贝构造时,应考虑深拷贝使得两者的堆内的值相互不影响
示例代码如下
#include <iostream>using namespace std;class String{public: String(const char* str = "") :_str(new char[strlen(str)+1]) { strcpy(_str, str); } String(String& s):_str(NULL) { String temp(s._str); swap(_str, temp._str); } void Release() { delete[] _str; } ~String() { Release(); } void show() { cout << _str << endl; }private: char* _str;};int main(){ String s1("haha"); String s2(s1); s2.show(); return 0;}
事实上这种深拷贝在“同一内容重复拷贝时”的情况下极大的浪费了空间、降低了效率。
写时拷贝&引用计数
形如百度网盘上传用户文件到服务器时,对于同一文件(如某软件安装包)服务器若将多个用户的同一文件独立存储,那么将浪费极大的存储空间。
正确的做法是:
- 在文件内容发生更改时进行深拷贝,在文件未发生变化时进行浅拷贝。
- 在文件内容剩最后一份需要析构时释放空间,否则不释放空间
以String类模拟时作代码如下
#include <iostream>using namespace std;class String{public: String(const char* str = "") :_str(new char[strlen(str)+1]) ,_refCount(new int(1)) { strcpy(_str, str); } String(String& s) { _str = s._str; _refCount = s._refCount; ++(*_refCount); } String& operator=(const String& s) { if (_str != s._str) { Release();//原空间计数器-1 _refCount = s._refCount;//新空间计数器替换 _str = s._str;//替换指针地址 ++(*_refCount);//新空间计数器++ } return *this; } char& operator[](size_t index) { CopyOnWrite(); return _str[index]; } ~String() { Release(); } void Release() { if(--(*_refCount) == 0) { delete[] _str; delete _refCount; printf("delete: 0x%p\n", (void*)_str); } } void CopyOnWrite()//写时拷贝,为该对象申请新的空间 { if (*_refCount > 1) { char* tmp = new char[strlen(_str)+1]; strcpy(tmp, _str); --(*_refCount); _str = tmp; _refCount = new int(1); } }private: char* _str; int* _refCount;};int main(){ String s1("haha"); String s2(s1); return 0;}
对引用计数器的改进
易知,引用计数器的使用在堆上申请了新的空间,因此合并其空间到字符串的堆空间有如下好处
- 尽量申请大片内存,减少内存碎片
- 少申请一个变量,减少栈帧的空间的消耗。
如图所示
代码如下
#include <iostream>using namespace std;class String{public: String(const char* str = "") :_str(new char[strlen(str)+5]) { _str += 4; get_ref() = 1; strcpy(_str, str); } int& get_ref() { return *((int*)(_str-4)); } String(String& s) { _str = s._str; ++get_ref(); } String& operator=(const String& s) { if (_str != s._str) { Release();//原空间计数器-1 _str = s._str;//替换指针地址 ++(get_ref());//新空间计数器++ } return *this; } char& operator[](size_t index) { CopyOnWrite(); return _str[index]; } ~String() { Release(); } void Release() { if(--(get_ref()) == 0) { _str -= 4; delete[] _str; printf("delete: 0x%p\n", (void*)_str); } } void CopyOnWrite()//写时拷贝,为该对象申请新的空间 { if (get_ref() > 1) { char* tmp = new char[strlen(_str)+5]; tmp += 4; strcpy(tmp, _str); --(get_ref()); _str = tmp; get_ref() = 1; } }private: char* _str;};int main(){ String s1("haha"); String s2(s1); return 0;}
阅读全文
0 0
- 浅析深拷贝之写时拷贝&引用计数
- 深浅拷贝&引用计数写时拷贝
- 引用计数+写时拷贝
- 引用计数写时拷贝
- 引用计数写时拷贝
- 引用计数写时拷贝
- 引用计数+写时拷贝
- 引用计数--写时拷贝
- String类---深拷贝,简洁深拷贝,引用计数拷贝,写时拷贝
- C++::浅拷贝,深拷贝,引用计数的拷贝,写时拷贝
- C++浅拷贝、深拷贝及引用计数浅析
- 由深拷贝与浅拷贝引发的引用计数、写时拷贝技术
- String类详解(浅拷贝,深拷贝,引用计数,写时拷贝)
- String类的浅拷贝、深拷贝、引用计数、写时拷贝
- 由深拷贝与浅拷贝引发的引用计数、写时拷贝技术
- C++写时拷贝,引用计数
- C++ 引用计数写时拷贝
- 引用计数的写时拷贝
- myeclipse安装svn插件及基本使用
- A. Voltage Keepsake
- 复杂对象的组装与创建——建造者模式(三)
- linux网络编程常用函数详解与实例
- Win10安装SQL Server2014关于.NET Framwork 3.5的问题
- 浅析深拷贝之写时拷贝&引用计数
- PC^2个人使用总结
- hive2.1.1 和 spark2.1.2
- 51Nod 1090 3个数和为0
- Spring MVC @ModelAttribute 详解
- TensorFlow(1)---官方文档简介中所给demo的解说
- Nginx和OpenResty专栏帖
- Objective-C底层数据结构
- 云服务 IaaS,PaaS,SaaS 的区别