写时拷贝COW(copy-on-write)

写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配4个字节,用来记录有多少个指针指向块空间,当有新的指针指向这块空间时,引用计数加一,当要释放这块空间时,引用计数减一(假装释放),直到引用计数减为0时才真的释放掉这块空间。当有的指针要改变这块空间的值时,再为这个指针分配自己的空间(注意这时引用计数的变化,旧的空间的引用计数减一,新分配的空间引用计数加一)。

#include<iostream>
#include<new.h>
#include<string>
using namespace std;

//1解决内存泄漏
//2编写赋值语句
//3写时拷贝
class String;
ostream& operator<<(ostream &out, const String &s);

/////////////////////////////////////////////////////////////////////
class String_rep
{
	friend class String;
	friend ostream& operator<<(ostream &out, const String &s);

private:
	String_rep(const char *str = "") : use_count_(0)
	{
		if (str == NULL)
		{
			data = new char[1];
			data[0] = ‘\0‘;
		}
		else
		{
			data = new char[strlen(str) + 1];
			strcpy(data, str);
		}
	}
	String_rep(const String_rep &rep)
	{
		this->data = rep.data;
	}
	String_rep& operator=(const String_rep &rep)
	{
		this->data = rep.data;
	}
	~String_rep()
	{
		if (data != NULL)
		{
			delete[]data;
			data = NULL;
		}
	}
public:
	void increment()
	{
		++use_count_;
	}

	void decrement()
	{
		//引用计数为0,释放共享内存
		if (--use_count_ == 0)
			delete this;
	}

private:
	char *data;
	int use_count_;
};

//////////////////////////////////////////////////////
class String
{
	friend ostream& operator<<(ostream& out, const String &s);

public:
	String(const char *str = "") :rep(new String_rep(str))
	{
		rep->increment();
	}
	String(const String &s)
	{
		rep = s.rep;
		rep->increment();
	}
	String& operator=(const String &s)
	{
		if (&s != this)
		{
			this->rep->decrement();	  //原有共享内存中的引用计数减一
			this->rep = s.rep;
			this->rep->increment();	  //现有引用计数加一
		}
		return *this;
	}
	~String()
	{
		//String析构一次,引用计数减一
		rep->decrement();
	}

public:
	void to_upper();
	String& operator+=(const String &str);

private:
	String_rep *rep;
};

/////////////////////////////////////////////////////////////////////////
ostream& operator<<(ostream &out, const String &s)
{
	out << s.rep->data;
	return out;
}

//创建新的共享内存原来共享内存中值一样,然后再修改
void String::to_upper()
{
	String *newStr = new String(this->rep->data);
	this->rep->decrement();
	this->rep = newStr->rep;
	this->rep->increment();

	char *str = this->rep->data;
	while (*str != ‘\0‘)
	{
		*str -= 32;
		++str;
	}
	delete newStr;
}

String& String::operator+=(const String &str)
{
	char *ch = new char[strlen(str.rep->data) + strlen(this->rep->data) + 1];
	strcpy(ch,this->rep->data);
	strcat(ch, str.rep->data);

	this->rep->decrement();
	String_rep *s = new String_rep(ch);
	this->rep = s;
	this->rep->increment();

	return *this;
}

int main()
{
	String s("abc");
	String s1;
	s1 = s; //
	String s2("xyz");
	String s3(s);
	s2.to_upper();

	s3 += s2;
	cout << s2 << endl;
	cout << s3 << endl;

	return 0;
}
时间: 2024-10-15 18:44:06

写时拷贝COW(copy-on-write)的相关文章

写时拷贝(copy-on-write) COW技术

时间:2014.05.06 地点:基地二楼 ---------------------------------------------------------------------------------- 一.写时拷贝的概念--COW技术在Linux进程上的应用 Linux在使用fork()函数进程创建时,传统fork()的做法是系统把所有的资源复制给新创建的进程,这种方式不仅单一,而且效率低下.因为所拷贝的数据或别的资源可能是可以共享的.现在Linux的fork()使用写时拷贝页来实现新进

写时拷贝(copy on write)

;写时拷贝(copy on write) 即某个对象的堆指针成员平时和其他对像的堆指针成员平时它们几个共享同一份实值 ,知道这个独享的值必须发生改写的时候才停止共享,而将该值重新申请一份空间存放自己私有的东西

分析 写时拷贝 的四个方案(Copy On Write)

深拷贝效率低,我们可以应引用计数的方式去解决浅拷贝中析构多次的问题. 首先要清楚写时拷贝是利用浅拷贝来解决问题!! 方案一 class String { private: char* _str; int _refCount; }; 方案一最不靠谱,它将用作计数的整形变量_refCount定义为类的私有成员变量,任何一个对象都有它自己的成员变量_refCount,它们互不影响,只要拷贝出了对象,_refCount大于了1,那么每个对象调用自己的析构函数时--_refCount不等于0,那么它们指向

写时拷贝技术

Copy On Write(COW):写时拷贝技术 一.什么是写时拷贝技术: 写时拷贝技术可以理解为"写的时候才去分配空间",这实际上是一种拖延战术. 举个栗子: 二.写时拷贝技术原理: 写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配4个字节,用来记录有多少个指针指向块空间,当有新的指针指向这块空间时,引用计数加一,当要释放这块空间时,引用计数减一(假装释放),直到引用计数减为0时才真的释放掉这块空间.当有的指针要改变这块空间的值时,再为这个指针分配自

C++ String类写时拷贝

    维基百科:     写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略.其核心思想是,如果有多个调用者(callers)同时要求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变.这过程对其他的调用者都是透明的(transparently).此作法主要的优点是如果调用者没有修

Linux写时拷贝技术【转】

本文转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/20/2601655.html COW技术初窥: 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程. 那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢? 在fork之后exec之前两个进

String写时拷贝实现

头文件部分 1 /* 2 版权信息:狼 3 文件名称:String.h 4 文件标识: 5 摘 要:对于上版本简易的String进行优化跟进. 6 改进 7 1.(将小块内存问题与大块分别对待)小内存块每个对象都有,当内存需求大于定义大小时利用动态分配 8 2.实现大块内存的写时拷贝功能,提高效率,优化空间利用 9 3.类似new[]实现机制:将动态内存块大小信息保存为隐藏“头” 10 11 当前版本:1.2 12 修 改 者:狼 13 完成日期:2015-12-12 14 15 取代版本:1.

Linux写时拷贝技术(copy-on-write)

COW技术初窥: 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程. 那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢? 在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段.数据段.堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个.

c++ 写时拷贝

写时拷贝--Copy On Writ #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class String { public:  String(char *str = "") :_str(new char[strlen(str)+5])  {   _str += 4;   _GetRefCount(_str) = 1;   strcpy(_str, str);  }  Str