COW是一种延迟复制策略,多个对象共享数据直至写操作时才复制;C++11禁用std::string的COW因线程安全与标准冲突,现代改用SSO+深拷贝;shared_ptr体现指针级COW,对象级需cow_ptr封装;手写COW字符串因线程不友好、标准不符、调试困难等不再推荐。

写时复制(Copy-on-Write,简称 COW)是一种经典的延迟复制优化策略:多个对象共享同一份底层数据,直到其中某个对象尝试修改时,才真正复制一份独立副本。它在 C++ 中曾广泛用于 std::string(C++98/03 时期)和自定义容器,以减少不必要的内存分配与拷贝开销。但需注意——C++11 标准明确禁止了 std::string 的 COW 实现,因其与多线程安全、迭代器失效、引用透明性等产生严重冲突;现代标准库普遍采用短字符串优化(SSO)+ 深拷贝策略。
COW 字符串的典型实现逻辑
一个手动实现的 COW string 需管理“引用计数 + 共享缓冲区”,核心在于:构造、拷贝不复制数据,赋值/修改前检查引用计数并按需分离。
-
共享结构体:通常封装为带引用计数(atomic 或非 atomic,取决于线程模型)和字符数组的结构,如
struct string_data { size_t ref_count; char data[]; }; - 拷贝构造/赋值:仅递增引用计数,指针指向同一块内存;不触发 new/memcpy
-
写操作拦截:如
operator[]非 const 版本、append()、replace()等,先调用unshare()—— 若 ref_count > 1,则 new 新缓冲区、memcpy 原内容、递减旧计数、切换指针 - 析构与释放:ref_count 减至 0 时 delete[] 缓冲区
COW 在智能指针中的自然体现
事实上,std::shared_ptr 就是 COW 思想的标准化、线程安全实现——但它复制的是“指针控制块”(含引用计数),而非所指对象本身。对象本身仍被共享,修改仍影响所有持有者。
- 若你希望“对象级 COW”,即多个
shared_ptr<t></t>共享一份 T,但某次修改时自动克隆 T 的副本,需额外封装:例如定义cow_ptr<t></t>,内部持有一个shared_ptr<t></t>,并在写访问前调用make_unique<t>(*ptr)</t>复制对象 - 常见模式:
T& cow_ptr::operator*() { if (ptr.use_count() > 1) ptr = std::make_shared<t>(*ptr); return *ptr; }</t> - 注意:该方案适用于读多写少、T 可拷贝且拷贝成本可控的场景;频繁写入会抵消 COW 收益
为什么现代 C++ 不再推荐手写 COW 字符串?
不是技术不可行,而是代价常被低估:
标签: c++ 写时复制 app 工具 标准库 为什么 red
还木有评论哦,快来抢沙发吧~