2.2、 深入
在深入这前,通过上述的演示,我们应该知道在string类中,要实现写时才拷贝,需要解决两个问题,一个是内存共享,一个是Copy-On-Wirte,这两个主题会让我们产生许多疑问,还是让我们带着这样几个问题来学习吧:
1、 Copy-On-Write的原理是什么?
2、 string类在什么情况下才共享内存的?
3、 string类在什么情况下触发写时才拷贝(Copy-On-Write)?
4、 Copy-On-Write时,发生了什么?
5、 Copy-On-Write的具体实现是怎么样的?
喔,你说只要看一看STL中stirng的源码你就可以找到答案了。当然,当然,我也是参考了string的父模板类basic_string的源码。但是,如果你感到看STL的源码就好像看机器码,并严重打击你对C++自信心,乃至产生了自己是否懂C++的疑问,如果你有这样的感觉,那么还是继续往下看我的这篇文章吧。
OK,让我们一个问题一个问题地探讨吧,慢慢地所有的技术细节都会浮出水面的。
2.3、 Copy-On-Write的原理是什么?
有一定经验的程序员一定知道,Copy-On-Write一定使用了“引用计数”,是的,必然有一个变量类似于RefCnt。当第一个类构造时,string的构造函数会根据传入的参数从堆上分配内存,当有其它类需要这块内存时,这个计数为自动累加,当有类析构时,这个计数会减一,直到最后一个类析构时,此时的RefCnt为1或是0,此时,程序才会真正的Free这块从堆上分配的内存。
是的,引用计数就是string类中写时才拷贝的原理!
不过,问题又来了,这个RefCnt该存在在哪里呢?如果存放在string类中,那么每个string的实例都有各自的一套,根本不能共有一个RefCnt,如果是声明成全局变量,或是静态成员,那就是所有的string类共享一个了,这也不行,我们需要的是一个“民主和集中”的一个解决方法。这是如何做到的呢?呵呵,人生就是一个糊涂后去探知,知道后和又糊涂的循环过程。别急别急,在后面我会给你一一道来的。
2.3.1、 string类在什么情况下才共享内存的?
这个问题的答案应该是明显的,根据常理和逻辑,如果一个类要用另一个类的数据,那就可以共享被使用类的内存了。这是很合理的,如果你不用我的,那就不用共享,只有你使用我的,才发生共享。
使用别的类的数据时,无非有两种情况,1)以别的类构造自己,2)以别的类赋值。第一种情况时会触发拷贝构造函数,第二种情况会触发赋值操作符。这两种情况我们都可以在类中实现其对应的方法。对于第一种情况,只需要在string类的拷贝构造函数中做点处理,让其引用计数累加;同样,对于第二种情况,只需要重载string类的赋值操作符,同样在其中加上一点处理。
唠叨几句:
1)构造和赋值的差别
对于前面那个例程中的这两句:
string str1 = "hello world";
string str2 = str1;
不要以为有“=”就是赋值操作,其实,这两条语句等价于:
string str1 ("hello world"); //调用的是构造函数
string str2 (str1); //调用的是拷贝构造函数
如果str2是下面的这样情况:
string str2; //调用参数默认为空串的构造函数:string str2(“”);
str2 = str1; //调用str2的赋值操作:str2.operator=(str1);
2) 另一种情况
char tmp[]=”hello world”;
string str1 = tmp;
string str2 = tmp;
这种情况下会触发内存的共享吗?想当然的,应该要共享。可是根据我们前面所说的共享内存的情况,两个string类的声明和初始语句并不符合我前述的两种情况,所以其并不发生内存共享。而且,C++现有特性也无法让我们做到对这种情况进行类的内存共享。
|
2.3.2、 string类在什么情况下触发写时才拷贝(Copy-On-Write)?
哦,什么时候会发现写时才拷贝?很显然,当然是在共享同一块内存的类发生内容改变时,才会发生Copy-On-Write。比如string类的[]、=、+=、+、操作符赋值,还有一些string类中诸如insert、replace、append等成员函数,包括类的析构时。
修改数据才会触发Copy-On-Write,不修改当然就不会改啦。这就是托延战术的真谛,非到要做的时候才去做。
2.3.3、 Copy-On-Write时,发生了什么?
我们可能根据那个访问计数来决定是否需要拷贝,参看下面的代码:
If ( RefCnt>0 ) {
char* tmp = (char*) malloc(strlen(_Ptr)+1);
strcpy(tmp, _Ptr);
_Ptr = tmp;
}
|
上面的代码是一个假想的拷贝方法,如果有别的类在引用(检查引用计数来获知)这块内存,那么就需要把更改类进行“拷贝”这个动作。
我们可以把这个拷的运行封装成一个函数,供那些改变内容的成员函数使用。
<-上一页 下一页->
(版权所有,转载时请注明作者和出处)
分享到:
相关推荐
STL 字符串可以分为两类:copy-on-write 字符串和非 copy-on-write 字符串。copy-on-write 字符串在修改字符串时,会创建字符串的副本,而非 copy-on-write 字符串则不会创建副本。非 copy-on-write 字符串的性能...
在C++编程中,字符串处理是...总的来说,`String`类的实现利用了预分配内存和Copy-on-Write技术,旨在提供一种高效且易于使用的字符串处理工具。理解这些技术可以帮助我们在设计和实现自定义数据结构时更好地优化性能。
- **优化字符串复制**:对于频繁复制的场景,可以考虑引入“写时复制”(Copy-On-Write, COW)机制来提高效率。 - **预分配空间**:对于预期会增长的字符串,可以在构造函数中预分配一定的额外空间,以减少后续重新...
老实说,我几年前也有同样的痛苦(就是当我写下《标准C++类string的Copy-On-Write技术》之前的一段时间)。那时,我不得不研究那根本不是给人看的SGI出品的string类的源码,代码的可读性几乎为零,而且随着了解越...
写时拷贝(Copy-on-Write,COW)则是在尝试修改对象时才进行拷贝,如果只是读取,则可以共享同一份数据,节省内存。 在C++中,我们可以通过使用`std::shared_ptr`或`std::atomic`等工具来实现这一策略。以下是一些...
接着,`MyString(v2.0)`引入了"写时拷贝"(Copy-on-Write, COW)策略,配合引用计数来提高效率。当两个字符串共享同一内存区域时,只有在其中一个字符串被修改时才真正进行拷贝。引用计数用于跟踪共享同一个数据结构...
special offer, and write for full details on how to receive a free IntroPak containing a $15 credit toward your first month's on-line charges. 2. Check with your local software dealer or users' ...
C++标准库中的`std::string`类采用了Copy-On-Write技术,在字符串拷贝或赋值操作时延迟实际的内存复制,直到某个操作需要修改字符串内容时才进行复制,从而提高了程序的效率。 以上知识点涵盖了从基础语法到高级...
special offer, and write for full details on how to receive a free IntroPak containing a $15 credit toward your first month's on-line charges. 2. Check with your local software dealer or users' ...
Earlier versions of Delphi and C++ Builder will not be supported. If you need Delphi 3 or C++ Builder 3 support you will have to revert to version 3.7 of the Drag and Drop Component Suite. The ...
Classes Doing Work in Constructors Default Constructors Explicit Constructors Copy Constructors Structs vs. Classes Inheritance Multiple Inheritance Interfaces Operator Overloading Access Control ...
基于 C++ 的多线程拷贝技术 本文讲述基于 C++ 的多线程拷贝技术,包括实现流程和源代码程序。多线程拷贝技术可以大大提高文件拷贝速度,特别是在拷贝大文件时。 多线程拷贝技术实现流程 1. 把一个文件分成 N 份,...
- **格式转换**:使用`avformat_open_input`打开输入文件,`avformat_find_stream_info`获取流信息,`avformat_write_header`写入输出文件头部,然后读取AVPacket并用`av_interleaved_write_frame`写入输出文件,...
C++标准库是C++语言的核心组成部分,它包含了许多子库,如IO流库(iostream)、字符串处理库(string)、容器库(container,如vector、list、map等)、算法库(algorithm)、文件操作库(fstream)等。这些库提供了...
`std::string`类提供了许多操作字符串的方法,如`append`、`find`和`substr`等。 在cmath库中,你可以找到诸如`sqrt`(平方根)、`pow`(指数运算)、`sin`和`cos`(三角函数)等函数。而在ctime库中,`std::time`...
produced when this parameter was a null string (""). Now, the original input filename is used as the AML output filename, with an ".aml" extension. Implemented a generic batch command mode for the ...