标准C++类string的Copy-On-Write技术(一)

原创 2004年06月23日 16:06:00

标准C++类std::string的

内存共享和Copy-On-Write技术

 

陈皓

1、             概念

 

Scott Meyers在《More Effective C++》中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功课,于是你把自己关在房间里,做出一副正在复习功课的样子,其实你在干着别的诸如给班上的某位女生写情书之类的事,而一旦你的父母出来在你房间要检查你是否在复习时,你才真正捡起课本看书。这就是“拖延战术”,直到你非要做的时候才去做。

 

当然,这种事情在现实生活中时往往会出事,但其在编程世界中摇身一变,就成为了最有用的技术,正如C++中的可以随处声明变量的特点一样,Scott Meyers推荐我们,在真正需要一个存储空间时才去声明变量(分配内存),这样会得到程序在运行时最小的内存花销。执行到那才会去做分配内存这种比较耗时的工作,这会给我们的程序在运行时有比较好的性能。必竟,20%的程序运行了80%的时间。

 

当然,拖延战术还并不只是这样一种类型,这种技术被我们广泛地应用着,特别是在操作系统当中,当一个程序运行结束时,操作系统并不会急着把其清除出内存,原因是有可能程序还会马上再运行一次(从磁盘把程序装入到内存是个很慢的过程),而只有当内存不够用了,才会把这些还驻留内存的程序清出。

 

写时才拷贝(Copy-On-Write)技术,就是编程界“懒惰行为”——拖延战术的产物。举个例子,比如我们有个程序要写文件,不断地根据网络传来的数据写,如果每一次fwrite或是fprintf都要进行一个磁盘的I/O操作的话,都简直就是性能上巨大的损失,因此通常的做法是,每次写文件操作都写在特定大小的一块内存中(磁盘缓存),只有当我们关闭文件时,才写到磁盘上(这就是为什么如果文件不关闭,所写的东西会丢失的原因)。更有甚者是文件关闭时都不写磁盘,而一直等到关机或是内存不够时才写磁盘,Unix就是这样一个系统,如果非正常退出,那么数据就会丢失,文件就会损坏。

 

呵呵,为了性能我们需要冒这样大的风险,还好我们的程序是不会忙得忘了还有一块数据需要写到磁盘上的,所以这种做法,还是很有必要的。

 

 

2、             标准C++std::stringCopy-On-Write

 

在我们经常使用的STL标准模板库中的string类,也是一个具有写时才拷贝技术的类。C++曾在性能问题上被广泛地质疑和指责过,为了提高性能,STL中的许多类都采用了Copy-On-Write技术。这种偷懒的行为的确使使用STL的程序有着比较高要性能。

 

这里,我想从C++类或是设计模式的角度为各位揭开Copy-On-Write技术在string中实现的面纱,以供各位在用C++进行类库设计时做一点参考。

 

在讲述这项技术之前,我想简单地说明一下string类内存分配的概念。通过常,string类中必有一个私有成员,其是一个char*,用户记录从堆上分配内存的地址,其在构造时分配内存,在析构时释放内存。因为是从堆上分配内存,所以string类在维护这块内存上是格外小心的,string类在返回这块内存地址时,只返回const char*,也就是只读的,如果你要写,你只能通过string提供的方法进行数据的改写。

 

2.1、         特性

 

由表及里,由感性到理性,我们先来看一看string类的Copy-On-Write的表面特征。让我们写下下面的一段程序:

 


#include

#include

using namespace std;

 

main()

{

       string str1 = "hello world";

       string str2 = str1;

      

       printf ("Sharing the memory:/n");

       printf ("/tstr1's address: %x/n", str1.c_str() );

       printf ("/tstr2's address: %x/n", str2.c_str() );

      

    str1[1]='q';

       str2[1]='w';

 

       printf ("After Copy-On-Write:/n");

       printf ("/tstr1's address: %x/n", str1.c_str() );

       printf ("/tstr2's address: %x/n", str2.c_str() );

 

       return 0;

}

 

这个程序的意图就是让第二个string通过第一个string构造,然后打印出其存放数据的内存地址,然后分别修改str1str2的内容,再查一下其存放内存的地址。程序的输出是这样的(我在VC6.0g++ 2.95都得到了同样的结果):

 


> g++ -o stringTest stringTest.cpp

> ./stringTest

Sharing the memory:

        str1's address: 343be9

        str2's address: 343be9

After Copy-On-Write:

        str1's address: 3407a9

        str2's address: 343be9

 

从结果中我们可以看到,在开始的两个语句后,str1str2存放数据的地址是一样的,而在修改内容后,str1的地址发生了变化,而str2的地址还是原来的。从这个例子,我们可以看到string类的Copy-On-Write技术。

 

 下一页->

(版权所有,转载时请注明作者和出处)

C++基础---string类的data/c_str/copy

1.string中data/c_str/copy 1.1 std::string::data 原型: const char *data()const; 功能: string型字符串转化为char型...
  • cainv89
  • cainv89
  • 2015年09月03日 18:09
  • 1599

c++中string类中c_str()、data()、copy(p,n)函数的用法

标准库的string类提供了3个成员函数来从一个string得到c类型的字符数组:c_str()、data()、copy(p,n)。 1. c_str():生成一个const char*指针,指向以...
  • Andy20081251
  • Andy20081251
  • 2014年03月19日 14:14
  • 3060

C++——string的深拷贝与浅拷贝

在c++中,基本所有的类都要考虑深拷贝,浅拷贝与写时拷贝,根据不同的定义,选择适合自己的拷贝方式。时间类就可以用浅拷贝,而二叉树,string类就需要深拷贝。 string类在vs编译器下使用的深拷...
  • qq_36782456
  • qq_36782456
  • 2017年04月29日 16:12
  • 246

c++string的深拷贝

在c++中当我们想要去拷贝一个字符串的时候就会存在两种方式: 1 浅拷贝方式                   2深拷贝方式 浅拷贝: 所谓的浅拷贝就是让当前的指针指向一块已存在的区域,和其他指针...
  • zhang1308299607
  • zhang1308299607
  • 2017年07月10日 18:59
  • 544

[C++/STL] string字符串关于copy函数的C4996错误

今天晚上,在使用Visual Stdio 2013使用string类的copy函数时,编译出现以下错误: error C4996: 'std::basic_string,std::allocator...
  • qq_15567051
  • qq_15567051
  • 2015年11月22日 23:14
  • 2077

C++【拷贝构造】和【拷贝赋值】(实现自定义的string类)

拷贝构造的形式,何种情况会调用拷贝构造。 1.构造副本 2.以值的方式传参 3.以值的方式返回缺省的拷贝赋值只能实现浅拷贝,因此会带来对象与其副本之间的指针耦合问题,为了实现深拷贝,就需要自己定...
  • u010193457
  • u010193457
  • 2015年10月27日 14:10
  • 1454

String copy的实现

注意点: 1)有效性判断 2)边界值,考虑到最后的'\0' #include using namespace std; void strcopy(char *src,char *de...
  • chencheng126
  • chencheng126
  • 2015年02月04日 09:12
  • 475

String类的浅拷贝和深拷贝

拷贝有两种:深拷贝,浅拷贝    当出现类的等号赋值时,会调用拷贝函数。在未定义显示拷贝构造函数的情况下,系统会调用默认某种拷贝函数,由系统决定是浅拷贝还是深拷贝。浅拷贝能够完成成员的复制。当数据成员...
  • Scenlyf
  • Scenlyf
  • 2016年06月11日 18:52
  • 2562

string中c_str()、data()、copy(p,n)函数的用法

string中c_str()、data()、copy(p,n)函数的用法 摘要: basic_string char> 就是string类,即string类实际是个类模板 typedef  ...
  • haiross
  • haiross
  • 2015年06月04日 08:56
  • 1763

memccpy() -- string字符串的拷贝

相关函数: bcopy(), memcpy(), memmove(), strcpy(), strncpy() 表头文件: #include 定义函数: void *memccpy(...
  • wallwind
  • wallwind
  • 2012年12月06日 09:18
  • 2805
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:标准C++类string的Copy-On-Write技术(一)
举报原因:
原因补充:

(最多只允许输入30个字)