copy on write
B从A处复制了一个复杂对象,B当且仅当要写这个对象的时候才从A拷贝一份真实的数据过来。写时才拷贝(Copy-On-Write)技术,就是编程界“懒惰行为”——拖延战术的产物。举个例子,比如我们有个程序要写文件,不断地根据网络传来的数据写,如果每一次fwrite或是fprintf都要进行一个磁盘的I/O操作的话,都简直就是性能上巨大的损失,因此通常的做法是,每次写文件操作都写在特定大小的一块内存中(磁盘缓存),只有当我们关闭文件时,才写到磁盘上(这就是为什么如果文件不关闭,所写的东西会丢失的原因)。
#include <iostream>#include <cstring>#include <chrono>#include <vector>#include <sstream>#include <iterator>#include <algorithm>// COW stringstruct String {private:struct Impl {size_t length;size_t capacity;size_t use_count;Impl(size_t length, size_t capacity, size_t use_count):length(length),capacity(capacity),use_count(use_count) {}Impl(const Impl &other):length(other.length),capacity(other.capacity),use_count(other.use_count) {}};char* ptr;Impl* impl;public:explicit String(const char* str);String(const String &other);~String();struct WriteProxy {void operator= (char c) {if (ptr[index] != c && impl->use_count != 1) {char *new_data = new char[impl->capacity];strncpy(new_data, ptr, impl->length);ptr = new_data;Impl *new_impl = new Impl(*impl);--impl->use_count;new_impl->use_count = 1;impl = new_impl;}ptr[index] = c;}~WriteProxy() {std::clog << "delete WriteProxy" << std::endl;}char* &ptr;Impl* &impl;size_t index;};WriteProxy operator[](size_t index) {std::clog << "WriteProxy" << std::endl;return WriteProxy {ptr, impl, index};}char operator[](size_t index) const {std::clog << "char operator[]" << std::endl;return ptr[index];}friend std::ostream &operator<<(std::ostream &os, const String &str) {os << str.ptr << std::endl;return os;}};String::String(const char *str) {ptr = new char[strlen(str) + 1];strcpy(ptr, str);impl = new Impl {strlen(str), strlen(str) + 1, 1};}String::String(const String &other) {ptr = other.ptr;impl = other.impl;++impl->use_count;}String::~String() {--impl->use_count;if (impl->use_count == 0) {delete[] ptr;delete impl;}}int main() {String a("Hello");std::clog << a;String b(a);std::clog << b;String c(a);std::clog << c;auto jj = c[3];jj = '3';std::clog << a;std::clog << b;std::clog << c;return 0;}

核心代码
struct WriteProxy {void operator= (char c) {if (ptr[index] != c && impl->use_count != 1) {char *new_data = new char[impl->capacity];strncpy(new_data, ptr, impl->length);ptr = new_data;Impl *new_impl = new Impl(*impl);--impl->use_count;new_impl->use_count = 1;impl = new_impl;}ptr[index] = c;}char* &ptr;Impl* &impl;size_t index;};WriteProxy operator[](size_t index) {return WriteProxy {ptr, impl, index};}
将 String 类的 ptr 和 impl 传给了 char &ptr; Impl &impl; 所以在 WriteProxy 中是可以直接访问到 String 类中的 ptr 和 impl 。
