#String封装——读时共享,写时复制
本文由乌合之众瞎写http://my.oschina.net/oloroso
碰到过一位一直怀疑C++标准库(STL)效率的人,他说STL效率太低,企业开发根本不会用。我是持反对意见的。 说这话的人,肯定没有做过大量的调查。没有调查就没有发言权。 STL的效率是不低的,特别是当前的操作系统和硬件都以页为内存的基本管理单位,内存碎片的问题并不明显了。
前面说的与这里要说的是无关的,这里指向说一说String封装中的读共享,写复制。
学习过linux/unix系统编程的人,应该对读共享,写复制这个概念有一个比较清晰的了解,这个可见APUE的进程相关的章节。
##实现原理
这个实线原理其实很简单,如果学习了shared_ptr智能指针,那应该是可以猜得到的。
其实关键的地方就是引用计数了。如果在string对象拷贝构造或者赋值(用已有对象)的时候,不进行拷贝,而只是进行引用计数的增加,数据采用共享方式。而在需要进行写操作的时候,才进行真正的拷贝操作。
##代码实现
这里只是一个简单的实现,来说明这个原理,并没有多少实用价值。
#include <stdio.h>
#include <string.h>
struct shared_ptr{
    char*    data;    //数据
    int        ref;    //引用计数
};
class String{
    public:
        String(const char* str=NULL):iswrite(false)
        {
            p = new shared_ptr;
            if( str != NULL){
                p->data = new char[strlen(str)+1];
                strcpy(p->data,str);
            }
            else{
                p->data = new char[1];
                p->data[0]='\0';
            }
            p->ref = 1;
        }
        String(const String& s):iswrite(false)
        {
            p = s.p;
            p->ref += 1;
        }
        ~String()
        {
            if(p->ref == 1){
                delete p->data;
                delete p;
            }
            else{
                p->ref -=1;
            }
        }
        String& erase(int first,int last)
        {
            if(first < 0 ||last > strlen(p->data))return *this;
            if(!iswrite){    //如果不是可写状态
                shared_ptr* t=p;
                p = new shared_ptr;    //拷贝数据
                p->data = new char[strlen(t->data)+1];
                strcpy(p->data,t->data);
                p->ref = 1;
                t->ref -=1;    //原指向结构体引用计数减一
            }
            //擦除操作
            int len = strlen(p->data);
            for(int i = 0;i<len-last+1;++i){
                p->data[first + i] = p->data[last + i];
            }
            return *this;
        }
        void show() const
        {
            printf("ref = %d,data:%s\n",p->ref,p->data);
        }
    private:
        shared_ptr* p;    //数据
        bool        iswrite;//可写?
};
int main()
{
    String s1("hello world");
    String s2(s1);
    String s3(s2);
    s1.show();
    s2.show();
    s3.show();
    s2.erase(5,10);
    s1.show();
    s2.show();
    s3.show();
    return 0;
}
##运行结果
ref = 3,data:hello world
ref = 3,data:hello world
ref = 3,data:hello world
ref = 2,data:hello world
ref = 1,data:hellod
ref = 2,data:hello world
 
 
 
 
 
 