一、什么是写时拷贝技术?
写时拷贝技术可以理解为“写的时候才去分配空间”,这实际上是一种拖延战术。
举个栗子:
二、写时拷贝技术原理:
写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配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';
}