共享内存和写时复制或右值引用和移动语义

Shared memory and copy on write or rvalue references and move semantics?

本文关键字:引用 移动 语义 复制 内存 共享      更新时间:2023-10-16

通用容器(如Qt的容器中发现的)的共享内存/写时复制实现是否被c++ 11移动语义和右值引用所取代?

哪里一个失败而另一个成功?或者它们是互补的而不是替代的?

写时复制和移动语义都被用来优化在堆上保存数据的对象的值语义。例如,std::string既被实现为写时复制对象,又被实现为可移动对象。

所以写时复制和移动语义在这方面是相似的:如果你对"复制"的定义足够宽松,它们都可以用来优化"复制"。我有时将move语义描述为引用计数限制为0或1的写时复制,因此包含引用计数的字段被优化掉了。

std::lib中的所有容器现在都使用move语义,甚至以前允许使用copy-on-write的std::string现在也禁止这样做。如果我今天要编写一个新的客户容器,我会在选择写时复制之前使用move语义。

在c++ 11中仍然使用写时复制。如果您希望您的数据结构很少被写入,但经常被复制,并且许多客户端持有相同值的副本,那么写时复制仍然是一个很大的优势。

例如,我看到写时复制很好地用于保存复杂文档的撤销列表。在任何给定的提交(您希望保存状态的地方),自上次提交以来,只有一小部分大文档发生了更改。因此,复制文档以保存其状态意味着更新一堆引用计数,并实际上对一小部分进行更改(写时复制样式)。

Copy-on-write和move语义是完全不同的概念,各自服务于不同的目的。虽然有一个常见的用例:从函数返回一个对象,其中因为原始对象超出作用域,所以它实际上是一个移动,但在一般情况下它们是不同的:在copy on write的情况下,多个对象可以同时共享内容。对于move语义,只有一个对象具有特定时间点的内容。

与此有点正交的是,写时复制在多线程环境中有问题,因为可能有多个对象访问相同的数据(只读)和控制块(读/写),这需要以线程安全的方式进行管理。