一、什么是写时拷贝技术?
写时拷贝技术可以理解为“写的时候才去分配空间”,这实际上是一种拖延战术。
举个栗子:
二、写时拷贝技术原理:
写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配4个字节,用来记录有多少个指针指向块空间,当有新的指针指向这块空间时,引用计数加一,当要释放这块空间时,引用计数减一(假装释放),直到引用计数减为0时才真的释放掉这块空间。当有的指针要改变这块空间的值时,再为这个指针分配自己的空间(注意这时引用计数的变化,旧的空间的引用计数减一,新分配的空间引用计数加一)。
利用写时拷贝技术实现简单string类
//声明文件
#pragma once #include<string.h> #include<stdlib.h> #include<stdio.h> #include<iostream> using namespace std; class CString{ public: char* lpszBuff; public: CString(const char* buff = ""); CString(CString& other); CString& operator=(CString& other); ~CString(); char& operator[](size_t index); };
//实现文件
#include "StdAfx.h" #include "CopyOnWrite.h" CString::CString(const char* buff){ cout << "CString构造函数" << endl; lpszBuff = new char[strlen(buff) + 1 + 4];//前4个字节用来存放引用计,最后一个字节用来存放结尾符 int* pInt = (int*)lpszBuff; *pInt = 1;//引用计数的初始值设置成1 lpszBuff += 4; strcpy(lpszBuff, buff); } CString::CString(CString& other){ cout << "CString拷贝构造函数" << endl; lpszBuff = other.lpszBuff;//此处的顺序很重要!!! int* pInt = (int*)(lpszBuff-4); (*pInt)++; } CString& CString::operator=(CString& other){ cout << "CString赋值函数" << endl; if(this != &other){//防止自我复制 int* pInt = (int*)(lpszBuff-4); if(--(*pInt) == 0){ cout << "释放缓存:" << lpszBuff << endl; delete[] (lpszBuff-4); lpszBuff = NULL; } lpszBuff = other.lpszBuff;//此处的顺序很重要!!! pInt = (int*)(lpszBuff-4); (*pInt)++; } return *this; } CString::~CString(){ cout << "CString析构函数" << endl; int* pInt = (int*)(lpszBuff-4); if(--(*pInt) == 0){ cout << "释放缓存:" << lpszBuff << endl; delete[] (lpszBuff-4); lpszBuff = NULL; } } char& CString::operator[](size_t index){ int* pInt = (int*)(lpszBuff-4); if(*pInt == 1) return lpszBuff[index]; (*pInt)--; char* lpszTmp = lpszBuff; lpszBuff = new char[strlen(lpszTmp)+1+4]; lpszBuff += 4; strcpy(lpszBuff, lpszTmp); pInt = (int*)(lpszBuff-4); *pInt = 1; return lpszBuff[index]; }
//测试客户端
void main() { CString str1 = "I love China !"; CString str2 = str1; CString str3 = "How are you ?"; str3 = str2; str3[1] = 'i'; }