通用容器(如 Qt 容器中的容器)的共享内存/写入时复制是否被 C++11 移动语义和右值引用所取代?
一个失败,另一个成功?或者它们是互补的而不是替代的?
通用容器(如 Qt 容器中的容器)的共享内存/写入时复制是否被 C++11 移动语义和右值引用所取代?
一个失败,另一个成功?或者它们是互补的而不是替代的?
写入时复制和移动语义都已用于优化将数据保存在堆上的对象的值语义。 std::string
,例如已实现为写入时复制对象和启用移动的对象。
所以写时复制和移动语义在这方面是相似的:如果你足够松散地定义“复制”,它们都可以用来优化“复制”。我有时将移动语义描述为写时复制,引用计数被限制为 0 或 1,因此包含引用计数的字段被优化掉了。
std::lib 中的所有容器现在都使用移动语义,甚至std::string
以前被允许使用写时复制的容器现在被禁止这样做。如果我今天要编写一个新的客户容器,我会在选择写时复制之前使用移动语义。
在 C++11 中仍然可以使用写时复制。如果您希望您的数据结构很少被写入,但经常被复制,并且许多客户持有相同值的副本,那么写时复制仍然是一个巨大的胜利。
例如,我已经看到写时复制很好地用于保存复杂文档的撤消列表。在任何给定的提交(您想要保存状态的地方),自上次提交以来,只有一小部分大文档发生了变化。因此,制作文档副本以保存其状态意味着更新一堆引用计数,并实际对一小部分进行更改(写入时复制样式)。
Copy-on-write 和 move 语义是完全不同的概念,每个都有不同的目的。虽然有一个常见的用例:从函数返回一个对象,其中由于原始对象超出范围,它实际上是一个移动,但在一般情况下,它们有所不同:
通过写入时复制,多个同时处于活动状态的对象可以共享内容。使用移动语义,只有一个对象具有特定时间点的内容。
与此有点正交,写时复制在多线程环境中存在问题,因为可能有多个对象访问相同的数据(只读)和控制块(读/写),这需要以线程安全的方式进行管理.