zoukankan      html  css  js  c++  java
  • String封装——读时共享,写时复制

    碰到过一位一直怀疑C++标准库(STL)效率的人,他说STL效率太低,企业开发根本不会用。我是持反对意见的。
    说这话的人,肯定没有做过大量的调查。没有调查就没有发言权。
    STL的效率是不低的,足够满足现在的绝大部分需求了。特别是当前的操作系统和硬件都以页为内存的基本管理单位,并且32位的系统(嵌入式还挺多的,但是嵌入式对内存的需求很大的比较少吧)的已经不是很多了。内存碎片的问题也就并不明显了。

    前面说的与这里要说的是无关的,这里指向说一说String封装中的读共享,写复制。

    学习过linux/unix系统编程的人,应该对读共享,写复制这个概念有一个比较清晰的了解,这个可见APUE的进程相关的章节。

    实现原理

    这个实现原理其实很简单,如果学习了shared_ptr智能指针,那应该是可以猜得到的。

    其实关键的地方就是引用计数了。如果在string对象拷贝构造或者赋值(用已有对象)的时候,不进行拷贝,而只是进行引用计数的增加,数据采用共享方式。而在需要进行写操作的时候,才进行真正的拷贝操作。

    代码实现

    这里只是一个简单的实现,来说明这个原理,并没有多少实用价值。并且没有做到多线程安全。现在一般的也不会采取这种做法,因为现在内存都比较富裕了,还要解决多线程安全问题。VC6还是采用的COW技术,现在编译器自带的STL基本都不在采用,而改用(忘记名字了,原理就是内部使用一个数组,只有创建的字符串长度超过这个数组的时候,才进行内存分配)。

    #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]='';
    			}
    			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
    ",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
    
  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/oloroso/p/4594868.html
Copyright © 2011-2022 走看看