C++的std::string的读时也拷贝技术!
2010-07-26 11:15
239 查看
C++的std::string的读时也拷贝技术!
注:本篇文章转自http://coolshell.cn/?p=1443
嘿嘿,你没有看错,我也没有写错,是读时也拷贝技术。什么?我的错,你之前听说写过时才拷贝,嗯,不错的确有这门技术,英文是CopyOnWrite,简写就是COW,非常’牛’!那么我们就来看看这个’牛’技术的效果吧。
我们先编写一段程序
嗯,一个非常大的字符串,有10M字节的x,并且执行了100此拷贝。编译执行它,非常快,在我的虚拟机甚至不要1个毫秒。
现在我们来对这个string加点料!
现在我们再编译并执行这断程序,居然需要4~5秒!哇!非常美妙的写时才拷贝技术,性能和功能的完美统一。
我们再来看看另外一种情况!
我们生成了一个string,并保留了它首字符的引用,然后复制这个string,修改string中的首字符。因为写操作只是直接的修改了内存中的指定位置,这个string就根本不能感知到有写发生,如果写时才拷贝是不成熟的,那么我们将同时会修改original和clone两个string。那岂不是灾难性的结果?幸好上述问题不会发生。clone的值肯定是没有被修改的。看来COW就是非常的牛!
以上都证明了我们的COW技术非常牛!
有太阳就有黑暗,这句说是不是有点耳熟?
啊,居然也是4~5秒!你可能在想,我只是做了一个读,没有写嘛,这到底是怎么回事?难道还有读时也拷贝的技术!。
不错,为了避免了你通过[]操作符获取string内部指针而直接修改字符串的内容,在你使用了the_base[0]后,这个字符串的写时才拷贝技术就失效了。
C++标准的确就是这样的,C++标准认为,当你通过迭代器或[]获取到string的内部地址的时候,string并不知道你将是要读还是要写。这是它无法确定,为此,当你获取到内部引用后,为了避免不能捕获你的写操作,它在此时废止了写时才拷贝技术!
这样看来我们在使用COW的时候,一定要注意,如果你不需要对string的内部进行修改,那你就千万不要使用通过[]操作符和迭代器去获取字符串的内部地址引用,如果你一定要这么做,那么你就必须要付出代价。当然,string还提供了一些使迭代器和引用失效的方法。比如说push_back,等,你在使用[]之后再使用迭代器之后,引用就有可能失效了。那么你又回到了COW的世界!比如下面的一个例子
一切又恢复了正常!如果对[]返回引用进行了操作又会发生情况呢,有兴趣的朋友可以试试!结果非常令人惊讶。
另外:上述例子是在linux环境下编译的,使用STL是GNU的STL。windows上我用的是vs2003,但是非常明显vs2003一点都不支持COW。
这篇文章出自http://ridiculousfish.com/blog/archives/2009/09/17/i-didnt-order-that-so-why-is-it-on-my-bill-episode-2/这里,我使用了它的例子。但是我重新自己组织了内容。
编写这篇文章的同时,我还参考了耗子的《标准C++类string的Copy-On-Write技术》一文
注:本篇文章转自
嘿嘿,你没有看错,我也没有写错,是读时也拷贝技术。什么?我的错,你之前听说写过时才拷贝,嗯,不错的确有这门技术,英文是CopyOnWrite,简写就是COW,非常’牛’!那么我们就来看看这个’牛’技术的效果吧。
我们先编写一段程序
01 | #include<string> |
02 | #include<iostream> |
03 | #include<sys/time.h> |
04 |
05 | static long getcurrenttick() |
06 | { |
07 | long tick; |
08 | struct timevaltime_val; |
09 | gettimeofday(&time_val,NULL); |
10 | tick=time_val.tv_sec*1000+time_val.tv_usec/1000; |
11 | return tick; |
12 | } |
13 |
14 | int main() |
15 | { |
16 | stringthe_base(1024*1024*10, 'x' ); |
17 | long begin=getcurrenttick(); |
18 | for ( int i=0;i<100;++i){ |
19 | stringthe_copy=the_base; |
20 | } |
21 | fprintf (stdout, "耗时[%d]/n" ,getcurrenttick()-begin); |
22 | } |
现在我们来对这个string加点料!
1 | int main( void ){ |
2 | stringthe_base(1024*1024*10, 'x' ); |
3 | long begin=getcurrenttick(); |
4 | for ( int i=0;i<100;i++){ |
5 | stringthe_copy=the_base; |
6 | the_copy[0]= 'y' ; |
7 | } |
8 | fprintf (stdout, "耗时[%d]/n" ,getcurrenttick()-begin); |
9 | } |
我们再来看看另外一种情况!
1 | stringoriginal= "hello" ; |
2 | char &ref=original[0]; |
3 | stringclone=original; |
4 | ref= 'y' ; |
以上都证明了我们的COW技术非常牛!
有太阳就有黑暗,这句说是不是有点耳熟?
1 | int main( void ){ |
2 | stringthe_base(1024*1024*10, 'x' ); |
3 | fprintf (stdout, "the_base'sfirstcharis[%c]/n" ,the_base[0]); |
4 | long begin=getcurrenttick(); |
5 | for ( int i=0;i<100;i++){ |
6 | stringthe_copy=the_base; |
7 | } |
8 | fprintf (stdout, "耗时[%d]/n" ,getcurrenttick()-begin); |
9 | } |
不错,为了避免了你通过[]操作符获取string内部指针而直接修改字符串的内容,在你使用了the_base[0]后,这个字符串的写时才拷贝技术就失效了。
C++标准的确就是这样的,C++标准认为,当你通过迭代器或[]获取到string的内部地址的时候,string并不知道你将是要读还是要写。这是它无法确定,为此,当你获取到内部引用后,为了避免不能捕获你的写操作,它在此时废止了写时才拷贝技术!
这样看来我们在使用COW的时候,一定要注意,如果你不需要对string的内部进行修改,那你就千万不要使用通过[]操作符和迭代器去获取字符串的内部地址引用,如果你一定要这么做,那么你就必须要付出代价。当然,string还提供了一些使迭代器和引用失效的方法。比如说push_back,等,你在使用[]之后再使用迭代器之后,引用就有可能失效了。那么你又回到了COW的世界!比如下面的一个例子
01 | int main() |
02 | { |
03 | struct timevaltime_val; |
04 | stringthe_base(1024*1024*10, 'x' ); |
05 | long begin=0; |
06 | fprintf (stdout, "the_base'sfirstcharis[%c]/n" ,the_base[0]); |
07 | the_base.push_back( 'y' ); |
08 | begin=getcurrenttick(); |
09 | for ( int i=0;i<100;++i){ |
10 | stringthe_copy=the_base; |
11 | } |
12 | fprintf (stdout, "耗时[%d]/n" ,getcurrenttick()-begin); |
13 | } |
另外:上述例子是在linux环境下编译的,使用STL是GNU的STL。windows上我用的是vs2003,但是非常明显vs2003一点都不支持COW。
这篇文章出自
编写这篇文章的同时,我还参考了耗子的
相关文章推荐
- C++ 的std::string的“读时也拷贝”技术!
- C++的std::string的“读时也拷贝”技术!
- C++的std::string的“读时也拷贝”技术!
- C++的std::string的“读时也拷贝”技术!
- C++的std::string的“读时也拷贝”技术
- C++的std::string的“读时也拷贝”技术!
- zz C++的std::string的“读时也拷贝”技术
- c++ std::string转换为数字和bool行
- [C++]char* const char* std::string区分
- C/C++ std::string 切词
- C++ 由std::string转为LPCWSTR
- Linux Eclipse CDT C++提示 Type 'string' could not be resolved或Type 'std' could not be resolved
- std::string的内存共享和Copy-On-Write技术
- char * 转换为std::string是内存拷贝了吗?
- C++: std::string 与 Unicode 如何结合?
- 标准C++类std::string的内存共享和Copy-On-Write技术(转)
- C++ 编程之std::string的utils
- Mysql: Connect/C++ 使用过程中发现返回 std::string 造成的内存泄露
- 用lambda对std::list排序 - 力为的技术博客 - C++博客
- Android NDK编译C++ 'stoi' and 'to_string' is not a member of 'std'