碰到过一位一直怀疑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]='\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

转载于:https://www.cnblogs.com/oloroso/p/4594868.html

String封装——读时共享,写时复制相关推荐

  1. 进程共享(读时共享写时复制)

    父子进程之间在刚fork后.父子相同处: 全局变量..data..bbs..text.栈.堆.环境变量.用户ID.宿主目录(进程用户家目录).进程工作目录.信号处理方式等等,即0~3G的用户空间是完全 ...

  2. 写时拷贝/写时复制技术

    拷贝控制 C++提供两个拷贝控制函数 拷贝构造函数 拷贝赋值运算符重载 例如:String类 class String{public:String(const char* str = NULL);St ...

  3. C++ 写时拷贝 3

    http://blog.csdn.net/ljianhui/article/details/22895505 字符串一种在程序中经常要使用到的数据结构,然而在C中却没有字符串这种类型.在C++中,为了 ...

  4. Redis的读更新和写更新-如何保证Redis与数据库的数据一致性

    背景 日前面试的时候被问到我们项目里面使用Redis的时候是如何更新缓存的,我的回答是写操作的时候的时候把缓存删了,然后读操作的时候就会读取出来最新的值.面试管继续问:Redis的写时更新和读时更新有 ...

  5. 标准C++类std::string的内存共享和Copy-On-Write(写时拷贝)

    标准C++类std::string的内存共享,值得体会: 详见大牛:https://www.douban.com/group/topic/19621165/ 顾名思义,内存共享,就是两个乃至更多的对象 ...

  6. Apache Hudi的写时复制和读时合并

    Apache Hudi http://hudi.apache.org/ http://hudi.apache.org/docs/quick-start-guide.html Hudi是什么 Hudi将 ...

  7. 进程P1、P2、P3共享一个表格F,P1对F只读不写,P2对F只写不读,P3对F先读后写。进程可同时读F,但有进程写时,其他进程不能读和写。

    进程P1.P2.P3共享一个表格F,P1对F只读不写,P2对F只写不读,P3对F先读后写.进程可同时读F,但有进程写时,其他进程不能读和写.要求:(1)正常运行时不能产生死锁.(2)F的并发度要高. ...

  8. 写时复制,写时拷贝,写时分裂,Copy on write

    2019独角兽企业重金招聘Python工程师标准>>> 写时复制,写时拷贝,写时分裂 (Copy-on-write,简称COW)是计算机资源管理方面的一种优化技术,有着广泛的应用,比 ...

  9. C++ String类写时拷贝 4

    http://blog.51cto.com/zgw285763054/1839752 维基百科: 写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略.其核心思 ...

最新文章

  1. mysql数据库唯一性_mysql表的字段怎么设置唯一性
  2. python期末考试编程题_智慧树知到_Python程序设计基础_期末考试答案
  3. HTML CSS JavaScript 从一个表格到一个灰阶颜色表(目录)
  4. 编译服务器home文件夹,离线安装FastDFS-过程填坑
  5. 环境搭建:如何配置 vscode 远程开发 + 免密登录
  6. 李国浩20179307第二周作业
  7. Linux下快速搭建DNS服务器
  8. 太赞了:《Spring Framework 4.x 参考文档》最新中文版开放下载!
  9. jQuery原理第三天
  10. Facebook 的 AI 翻身之战!
  11. Mysql的存储过程(以Mysql为例进行讲解)
  12. VB之Collection---Collection集合类
  13. puppet详解(六)——exec资源详解
  14. JS流程控制语句 重复重复(for循环)语句结构: for(初始化变量;循环条件;循环迭代) { 循环语句 }...
  15. qpython做连点器脚本_「PyMouse」做个连点器给老师点赞
  16. Vue - 选择器拼音快速检索目标(pinyin-match)
  17. 计算机应用中格式刷怎么用,如何连续使用格式刷【搞定手段】
  18. 支付宝支付验证签名失败
  19. SMB CIFS DOMIAN
  20. 本题要求递归实现一个计算非负整数阶乘的简单函数。

热门文章

  1. linux登录指令 pgsql_命令行方式登录PostgreSQL
  2. 异步udpserver接收rtp转html5(一)
  3. lua执行shell命令6_Vim执行shell命令及使用Vim批量更改文件名
  4. 李迟2011年4月知识积累
  5. python中stacked_python – Django管理员StackedInline定制
  6. rocketmq 重复消费_消息队列 RocketMQ
  7. 95-36-210-ChannelHandler-系统Channel-TimeoutHandler
  8. 【Elasticsearch】Elasticsearch之元数据(meta-fields)介绍
  9. 【ElasticSearch】Es 源码之 RestController 源码解读
  10. Spring : SpringBoot的ApplicationRunner和CommandLineRunner