copy on read & copy on write

1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 int main() {
 6     string strA = "Copy on write";
 7     string strB = strA;
 8     string strC = strA;
 9     printf("strA: %p\r\n", strA.c_str());
10     printf("strB: %p\r\n", strB.c_str());
11     printf("strC: %p\r\n", strC.c_str());
12  
13     strA = "sdf";
14     strB = "23ddf";
15     strC = "adfkdanfkdnvkdfnvkfdv";
16     printf("After writing:\r\n");
17     printf("strA: %p\r\n", strA.c_str());
18     printf("strB: %p\r\n", strB.c_str());
19     printf("strC: %p\r\n", strC.c_str());
20  
21     return 0;
22 }

运行结果:

strA: 0x103c007d8
strB: 0x103c007d8
strC: 0x103c007d8
After writing:
strA: 0x103c00808
strB: 0x103c00828
strC: 0x103c00848
[Finished in 0.2s]

分析:

9,10,11行printf输出的strA,strB,strC的C格式字符串的首地址全部相同,可见他们共享一份内存数据。

看过《More Effective C++》的话,你知道这里运用了引用计数。到第9行为止"Copy on write"仅一份,引用计数为3.

13行执行后"Copy on write"的引用计数变为2,执行15行时引用计数为1,那两次输出的strC的地址应该一致才对。但是strC地址确实变了,也就是说确实发生了写时拷贝。why?

仔细看代码,发现原来strC之前的长度不够,因此strC还是会写时拷贝。

现在把15行改成 strC = "adfkda"; 两次输出的strC的地址就会一致了。

再看一个读时拷贝的例子:

#include <iostream>
#include <string>
using namespace std;

int main() {   
    string str1 = "hello world!";   
    string str2 = str1;   
    char* p1 = const_cast<char*>(str1.c_str());   
    p1[0] = 'T';
    printf("str1: %s \r\nstr2: %s\n", str1.c_str(), str2.c_str());

    string str3 = "hello world!";   
    string str4 = str3;   
    char* p2 = &(str3[0]);   
    p2[0] = 'g';   
    printf("str3: %s \r\nstr4: %s\n", str3.c_str(), str4.c_str());   
    return 0;   
}

运行结果:

str1: Tello world! 
str2: Tello world!
str3: gello world! 
str4: hello world!
[Finished in 0.2s]

使用c_str()方法取得str1的buf地址后,强转成了char*类型,并不会进行复制操作,只因c_str()只是一个读操作而已。当通过p1对buf进行修改后,str1和str2都被修改了。

p2使用了[]操作符,String对[]进行了重载,当你通过[]获得String的buf地址的时候,编译器并不知道是读是写(尽管这里只是读取),保险起见,String内部会有一个变量进行控制,一旦遇到这种情况,则取消写时拷贝技术,因此str3改变了,但是str4指向的是另一块内存,并无影响。

在这里,const_cast<>()强制转换就是罪魁祸首。

参见:《More Effective C++》引用计数这一章节
原文链接: https://www.cnblogs.com/pure/archive/2013/02/18/2915265.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/78221

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午6:27
下一篇 2023年2月9日 下午6:27

相关推荐