关于在“写时拷贝”发生的情况下直接操作string中内容出现的问题
浏览:2340次 出处信息
注:本文是公司同事的一个分享,由于很有代表性,特分享在此,希望对大家有用。
上次welkin在处理一个豆瓣的cgi时遇到1个奇怪的问题,就是对一个string对象的修改引起了另一个string对象的同步修改。后来定位到原有,是因为有函数对string对象的buf内容直接进行了操作,破坏了“写时拷贝”的规则。下面这个例子说明了问题是如何产生的,已经如何避免:
int main()
{
string str1 = \"abcd\";
string str2 = str1;
char *p1 = const_cast<char*>(str1.c_str());
p1[0] = \'o\';
//这里str1和str2同时被修改了
printf(\"%s %s\\n\", str1.c_str(), str2.c_str());
string str3 = \"abcd\";
string str4 = str3;
char *p2 = &(str3[0]);
p2[0] = \'o\';
//这里只有str3被修改,str4不变
printf(\"%s %s\\n\", str3.c_str(), str4.c_str());
return 0;
}
{
string str1 = \"abcd\";
string str2 = str1;
char *p1 = const_cast<char*>(str1.c_str());
p1[0] = \'o\';
//这里str1和str2同时被修改了
printf(\"%s %s\\n\", str1.c_str(), str2.c_str());
string str3 = \"abcd\";
string str4 = str3;
char *p2 = &(str3[0]);
p2[0] = \'o\';
//这里只有str3被修改,str4不变
printf(\"%s %s\\n\", str3.c_str(), str4.c_str());
return 0;
}
上面的程序的运行结果如下:
obcd obcd
obcd abcd
str1和str2被同时改变这个比较好理解。因为str2的初值为str1,根据“写时拷贝”原则,在str2的值或者str1的值不发生改变的时候,2个对象实际上指向了同一块内存地址。
然而我们使用c_str方法取出了str1的buf首地址,且强制转换成了char*类型,这个强制转换的操作就是破坏C++标准的罪魁祸首了。它使得编译器无法获知通过指针p1对buf内容的修改操作而自动进行拷贝操作,结果就是str1和str2对象都被修改了。
而str3和str4为什么没有被同时修改呢。原因是指针p2的取值方式,它使用了[]操作符。C++标准认为,当你通过迭代器或[]获取到string的内部地址的时候,string并不知道你将是要读还是要写。这是它无法确定,为此,当你获取到内部引用后,为了避免不能捕获你的写操作,它在此时废止了“写时拷贝”技术!
实际上,将const char*强制转换为char*类型是问题的根本原因,他破坏了C++标准,我们应该尽量避免这么做。但现实是我们已经有很多接口这样实现了,这是一种典型的像C一样使用C++的行为。所以如果你遇到这种情况,记得使用[]操作符来获取string的第一个字符的地址,而不要使用c_str方法。
建议继续学习:
- 一个简单的stl中string的split函数 (阅读:3264)
- String,StringBuffer,StringBuilder的区别 (阅读:3015)
- Java将Object对象转换为String的总结合集 (阅读:2936)
- 关于在函数调用时传递string引用的必要性 (阅读:2845)
- 不得不留意的STL string重载函数和隐式类型转换 (阅读:1391)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
扫一扫订阅我的微信号:IT技术博客大学习
<< 前一篇:关于在函数调用时传递string引用的必要性
后一篇:C 语言中统一的函数指针 >>
文章信息
- 作者:Dante 来源: Vimer
- 标签: string 写时拷贝
- 发布时间:2010-06-24 09:48:28
建议继续学习
近3天十大热文
- [46] 界面设计速成
- [43] Oracle MTS模式下 进程地址与会话信
- [43] 视觉调整-设计师 vs. 逻辑
- [42] android 开发入门
- [42] IOS安全–浅谈关于IOS加固的几种方法
- [39] 图书馆的世界纪录
- [38] 程序员技术练级攻略
- [38] 【社会化设计】自我(self)部分――欢迎区
- [38] 如何拿下简短的域名
- [34] 读书笔记-壹百度:百度十年千倍的29条法则