概念
Copy-On-Write是一种技术——去高效的完成“懒惰行为”。其核心思想就是:只有在需要分配内存的时候才会进行内存分配。这种思想广泛的运用在操作系统和C++编程中。
在操作系统当中,当一个程序运行结束时,操作系统并不会急着把其清除出内存,原因是有可能程序还会马上再运行一次,而只有当内存不够用了,才会把这些还驻留内存的程序清出。这样既尽可能地减少了CPU读取磁盘的次数,又可以保证功能的正确性。
在C++中Copy-On-Write技术被广泛地应用于智能指针和字符串类等地方。例如在QT的框架中,许多类型应用了该技术,QT的术语叫做隐式共享(”implicialy shared”), 通过compare-and-swap 操作增减内部参考计数器来完成操作。因为复制时相对廉价的,所以QT可以经常安全地使用多线程。
目的
- 对于某些类而言,每一次都执行深拷贝会极大的降低执行效率,为了提高计算机执行效率
- 确保在需要进行深拷贝的时候(内容被改变的时候)执行深拷贝,确保程序的准确性
方法:
设置一个计数器,标明引用的个数,当引用数量为0时,删除该对象:
1. 在对象生命周期结束(调用析构函数)or需要写入的时候,计数器减一
2. 在执行拷贝构造or赋值函数的时候,计数器加一
3. 在赋值函数中,输入的左值将被重新赋值,所以需要将之前所指向的地址的计数器减一
implementation
一个简单的智能指针的实现
#include <iostream>
using namespace std;
template
<typename T>
class CowPtr{
protected:
struct Ptr{
T* point;
unsigned int counter;
};
Ptr* ptr;
void detach();
public:
CowPtr(const T* p =NULL);
CowPtr(const CowPtr& cp);
CowPtr& operator=(const CowPtr& cp);
unsigned int GetCount() const;
T* GetPoint() const;
T& operator *();
T operator *() const;
T* operator ->();
const T* operator ->() const;
~CowPtr();
};
template
<typename T>
void CowPtr<T>::detach(){
if(ptr->counter != 1){
Ptr* temp = new Ptr;
temp->point = ptr->point;
temp->counter = ptr->counter;
ptr = temp;
}
}
template
<typename T>
CowPtr<T>::CowPtr(const T* p){
ptr = new Ptr;
ptr->point = const_cast<T*>(p);
ptr->counter = 1;
}
template
<typename T>
CowPtr<T>::CowPtr(const CowPtr<T>& cp){
ptr = cp.ptr;
ptr->counter++;
}
template
<typename T>
CowPtr<T>& CowPtr<T>::operator=(const CowPtr<T>& cp){
if( (this!=&cp)|| (ptr != cp.ptr)){
if((ptr->counter--) == 0){
delete ptr->point;
delete ptr;
}
ptr= cp.ptr;
ptr->counter++;
}
return *this;
}
template
<typename T>
unsigned int CowPtr<T>::GetCount() const{
return ptr->counter;
}
template
<typename T>
T* CowPtr<T>::GetPoint() const{
return ptr->point;
}
template
<typename T>
T& CowPtr<T>::operator *(){
return *(ptr->point);
}
template
<typename T>
T CowPtr<T>::operator *() const{
return *(ptr->point);
}
template
<typename T>
T* CowPtr<T>::operator ->(){
return ptr->point;
}
template
<typename T>
const T* CowPtr<T>::operator ->() const{
return ptr->point;
}
template
<typename T>
CowPtr<T>::~CowPtr(){
if((--ptr->counter) == 0){
delete ptr->point;
delete ptr;
ptr = NULL;
}
}
class Test {
int i;
public:
Test(){
cout<<"Test()"<<endl;
}
~Test(){
cout<<" ~Test()"<<endl;
}
};
int main()
{
CowPtr<Test> cp = new Test;
cout<<cp.GetPoint()<<endl;
cout<<cp.GetCount()<<endl;
CowPtr<Test> cp1 = cp;
cout<<cp1.GetPoint()<<endl;
cout<<cp1.GetCount()<<endl;
CowPtr<Test> cp2;
cp2 = cp;
cout<<cp2.GetPoint()<<endl;
cout<<cp2.GetCount()<<endl;
printf("Hello World");
return 0;
}
这个只实现了部分功能,每有一个指针指向共享内存,计数器加一,计数器为0的时候释放内存。但是没有实现在写的时候自动拷贝的功能