C++的std::string的“读时也拷贝”技术!
2009-10-13 15:51
281 查看
C++的std::string的“读时也拷贝”技术!
赵锟
原文:http://coolshell.cn/?p=1443
C++的std::string的读时也拷贝技术!
嘿嘿,你没有看错,我也没有写错,是读时也拷贝技术。什么?我的错,你之前听说写过时才拷贝,嗯,不错的确有这门技术,英文是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技术》一文
赵锟
原文:
C++的std::string的读时也拷贝技术!
嘿嘿,你没有看错,我也没有写错,是读时也拷贝技术。什么?我的错,你之前听说写过时才拷贝,嗯,不错的确有这门技术,英文是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.
}
嗯,一个非常大的字符串,有10M字节的x,并且执行了100此拷贝。编译执行它,非常快,在我的虚拟机甚至不要1个毫秒。
现在我们来对这个string加点料!
01.
int
main(
void
){
02.
stringthe_base(1024*1024*10,
'x'
);
03.
long
begin=getcurrenttick();
04.
for
(
int
i=0;i<100;i++){
05.
stringthe_copy=the_base;
06.
the_copy[0]=
'y'
;
07.
}
08.
fprintf
(stdout,
"耗时[%d]/n"
,getcurrenttick()-begin);
09.
}
现在我们再编译并执行这断程序,居然需要4~5秒!哇!非常美妙的写时才拷贝技术,性能和功能的完美统一。
我们再来看看另外一种情况!
1.
stringoriginal=
"hello"
;
2.
char
&ref=original[0];
3.
stringclone=original;
4.
ref=
'y'
;
我们生成了一个string,并保留了它首字符的引用,然后复制这个string,修改string中的首字符。因为写操作只是直接的修改了内存中的指定位置,这个string就根本不能感知到有写发生,如果写时才拷贝是不成熟的,那么我们将同时会修改original和clone两个string。那岂不是灾难性的结果?幸好上述问题不会发生。clone的值肯定是没有被修改的。看来COW就是非常的牛!
以上都证明了我们的COW技术非常牛!
有太阳就有黑暗,这句说是不是有点耳熟?
01.
int
main(
void
){
02.
stringthe_base(1024*1024*10,
'x'
);
03.
fprintf
(stdout,
"the_base'sfirstcharis[%c]/n"
,the_base[0]);
04.
long
begin=getcurrenttick();
05.
for
(
int
i=0;i<100;i++){
06.
stringthe_copy=the_base;
07.
}
08.
fprintf
(stdout,
"耗时[%d]/n"
,getcurrenttick()-begin);
09.
}
啊,居然也是4~5秒!你可能在想,我只是做了一个读,没有写嘛,这到底是怎么回事?难道还有读时也拷贝的技术!。
不错,为了避免了你通过[]操作符获取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用法总结
- C++的std::to_string():数值转换字符串
- C++ std::string 不可初始化为NULL及基本用法
- C++ 中涉及到的 字符串转换 std::string CString char* Int 等
- C++当中,#include <string> 和 using std::string
- c++-----string和深浅拷贝
- VS2005:C++ std::string, std::wstring转换方法
- 几种C++ std::string和std::wstring相互转换的转换方法
- c++ int convert to std::string 转换成std::string
- c++ 中文std::string转std::wstring
- 几种C++ std::string和std::wstring相互转换的转换方法
- C++中,如何在标准库的std::string和常用库(Qt,VC等)的QString之间进行选择?
- C++ 工程实践(10):再探std::string