看了酷壳的文章,自己总结了一下。(Copy-On-Write)写时拷贝技术主要时为提高STL的效率而诞生的(这里的写时拷贝有点类似于linux上父子进程之间共享代码数据时的写时拷贝),从string类开始说明。
这里string类里必包含char* ,所以会在堆上开辟空间,返回const char*,析构时也要释放内存。所以当发生赋值,或拷贝构造时,会发生写时拷贝,要从新编写拷贝构造函数,赋值表达式重载,析构函数。
刚开始只是有赋值情况产生时,只要没有数据的改动或者迭代器的变化,系统为提高效率不会从新开辟空间,而是将两个指针指向同一空间,当数据的改动或者迭代器的变化时,才重新开辟空间。
#include<stdio.h>
#include<string>
using namespace std;
int main() {
string str1 = "hello world";
string str2 = str1;
printf("Sharing the memory:\n");
printf("/tstr1's address: %x\n", str1.c_str());
printf("/tstr2's address: %x\n", str2.c_str());
str1[1] = 'a';
str2[1] = 's';
printf("After Copy-On-Write:\n");
printf("/tstr1's address: %x\n", str1.c_str());
printf("/tstr2's address: %x\n", str2.c_str());
return 0;
}
将str1赋值给str2,并同时进行修改。这里分别在linux和vs进行实验。
发现刚开始str1和str2的地址时一样的,在进行各自赋值时地址发生改变,这就是写时拷贝。
而在vs下的结果不同
str1和str2的地址不同,这是vs进行了优化,但在调试时还会提示此表达式存在副作用,不予计算。
当诸如 []、=、+=、+、操作符赋值,还有一些string类中诸如insert、replace、append等成员函数,包括类的析构时,或者迭代器失效的情况,不会发生写时拷贝,系统重新开辟空间,运行速度变慢,当这些情况发生时,可以使用push_back等重新让程序进行写时拷贝。(这里有点类似于make_heap(),在将数据插入后在进行push_heap()重新建堆的情况)