C++写时拷贝
来源:互联网 发布:四层横移编程 编辑:程序博客网 时间:2024/06/05 23:01
写时拷贝copy on write
**首先什么时候会用到写时拷贝呢?
答:顾名思义修改的时候才拷贝,是为了解决浅拷贝的坑和平衡内存开销大而出的解决方案。
浅拷贝的坑——就是多个对象共用同一地址,在析构时同一块空间被释放多次,这种情况是不被允许的。
内存开销大——就是在每一次 深拷贝 时系统会新开辟空间,用来存放新对象。每创建一个新对象,就会开辟空间。每新开辟空间自然就会占内存,就会存在内存开销╮(╯_╰)╭。
深拷贝——就是为了“填浅拷贝的坑”,为新对象开辟新空间。
为了防止多次析构,但是还要考虑内存开销。我们想到用 引用计数(_refCount) 来起到一个内存使用的记录作用,让使用者清楚这块空间被who共用。在这块空间被析构时保证只有一个对象使用,即引用计数是1。当引用计数为0,这块空间真正被释放。
引用计数——即防止多个对象用一块空间时,这块空间被多次释放,用到的一个计数器。
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<cstdio>using namespace std;namespace COW{ class String { public: String(const char* str) :_str(new char[strlen(str) + 1]) , _refCount(new int(1)) { strcpy(_str, str); } // s2(s1) String(String& s) { _str = s._str; _refCount = s._refCount; ++(*_refCount); } // s2 = s4 String& operator=(const String& s) { if (_str != s._str) { Release(); _str = s._str; _refCount = s._refCount; (*_refCount)++; } return *this; } void Release() { if (--(*_refCount) == 0) { cout << "delete" << endl; delete[] _str; delete _refCount; } } char& operator[](size_t pos) { CopyOnWrite(); return _str[pos]; } char operator[](size_t pos) const { return _str[pos]; } void CopyOnWrite() { if (*_refCount > 1) { char* tmp = new char[strlen(_str) + 1]; strcpy(tmp, _str); --(*_refCount); _str = tmp; _refCount = new int(1); } } // Insert // Erase ~String() { Release(); } private: char* _str; int* _refCount; };
这里测试时:
void TestString() { String s1("hello world"); String s2(s1); String s3(s1); String s4("aaaaaaaaaaa"); String s5(s4); s2 = s4; }
对于这个例子,我们还可以做一个优化,可以模仿new[]底层实现来开辟空间,让引用计数占用前四个字节的空间 。
优化代码如下:
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<cstdio>using namespace std;namespace COW{ class String { private: char*_str; public: String(const char* str) :_str(new char[strlen(str) + 5]) { //*((int*)_str) = 1; _str += 4; strcpy(_str, str); GetRefCount()=1; } int& GetRefCount() { return *((int*)(_str - 4)); } ~String() { //if (--*((int*)_str - 4) == 0) if (--GetRefCount()==0) { cout << "delete" << endl; delete[](_str - 4); } } String(const String&s) :_str(s._str) { //(*(int*)(_str - 4))++; ++GetRefCount(); } String& operator=(const String& s) { if (_str != s._str) { if (--GetRefCount() == 0) { delete[](_str - 4); } _str = s._str; GetRefCount()++; } return *this; } const char* GetStr() { return _str; } }; void TestString() { String s1("hello"); cout << s1.GetStr() << endl; String s2 = s1; cout << s2.GetStr() << endl; }}
阅读全文
0 0
- C++String深浅拷贝、写时拷贝
- 【C++】写时拷贝COW
- 【C++】深拷贝、浅拷贝和写时拷贝
- 【c++】深浅拷贝,引用计数写时拷贝
- 【C++】String_COW(写时拷贝)
- C/C++ — 写时拷贝
- C++::浅拷贝,深拷贝,引用计数的拷贝,写时拷贝
- 【C++】浅析浅拷贝,深拷贝及写时拷贝(copy_on_write),模拟实现String类。
- 深拷贝&浅拷贝&写时拷贝
- 【C++】c++写时拷贝Copy On Write
- 【C语言】String类的写时拷贝
- 写时拷贝技术
- linux 写时拷贝
- fork写时拷贝
- 写时拷贝
- c++ 写时拷贝
- 写时拷贝
- C++ 写时拷贝
- SDWebImage 源码分析
- [代码分享]用JS写中文版99乘法表
- 2017多校第二场 HDU 6052 To my boyfriend 思维,计数题
- 根据动态二维数组输出一个稀疏矩阵,根据我自己想输入的稀疏矩阵来输出对应的三元组
- MySql问题积累
- C++写时拷贝
- 1067. Sort with Swap(0,*) (25)
- 从Javascript向Chrome插件传递int参数的问题
- C语言:gets/puts输入输出字符串
- 【unity3d学习笔记】RPG 中控制相机距离拉近拉远以及旋转相机视角
- 软件设计原则-- 开放-封闭原则
- 浪里个浪 FZU
- HDU_【2017 Multi-University Training Contest 1】——1001 Add More Zero
- STL之迭代器与traits编程技法