前言:写时复制是一种比价常用的技术,Linux进程fork,VC6的String类等等,都使用了写时复制。下面利用MString类来实现一下COW,以进一步明白其中原理。
MString类设计
在我前两篇博客中实现了MString的基础实现和运算符重载(http://blog.csdn.net/z702143700/article/details/47166437;http://blog.csdn.net/z702143700/article/details/47166343)
要实现COW,其实很简单的,只需要修改拷贝构造,赋值构造,修改字符串的类,添加引用计数变量即可。
添加引用计数变量
在MString.h中添加:size_t *m_used;
代表引用的个数。
拷贝构造、赋值构造、构造函数
拷贝构造
MString::MString(const MString& s)
{
m_len = s.m_len;
m_str = s.m_str;
++*m_used;
}
赋值构造:
MString& MString::operator=(const MString& s)
{
m_len = s.m_len;
m_str = s.m_str;
++*m_used;
return *this;
}
构造函数:
MString::MString(size_t n)
{
m_len = n;
m_used = new int(1);
m_str = new char[n+1];
}
析构
MString::~MString()
{
--*m_used;
if(*m_used == 0)
{
if(m_str != null)
{
delete[] m_str;
m_len = -1;
}
delete m_used;
m_used =NULL;
}
}
写时拷贝
只要有修改字符串的情况,都要实现复制操作,需要注意的就是让m_used减1,重新创建一个新的MString类,。注意所有类[]、赋值等的左值情况需要重载与MString相关的全局操作符。
最后,开始准备写一个完备的COW技术的MString后来发现,其实没有多大意义,打开VC6的string源码,里面实现的非常完美。关于COW技术,其实只要理解其实现基本原理即可,当我们在实际应用的时候,要根据不同的逻辑来实现,比如在IO缓存中,当缓冲池满了或关闭的情况才去将内容复制到设备上。