共享内存和写入或右值引用上的副本和移动语义?

时间:2013-04-18 20:08:52

标签: c++ containers shared-memory rvalue-reference copy-on-write

一般容器的写入实现的共享内存/副本(如Qt的容器中的那些)是否被C ++ 11移动语义和右值引用所取代?

哪一个失败而另一个失败?或者它们是互补的而不是替代品吗?

2 个答案:

答案 0 :(得分:7)

写入和移动语义上的复制都已用于优化在堆上保存其数据的对象的值语义。例如,std::string已作为写时复制对象和启用移动的对象实现。

因此,写时复制和移动语义在这方面类似:如果您足够松散地定义“复制”,它们都可用于优化“复制”。我有时将移动语义描述为写入时复制,引用计数限制为0或1,因此包含引用计数的字段被优化掉。

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

在C ++ 11中仍然可以使用copy-on-write。如果您希望您的数据结构很少被写入,但经常被复制,许多客户端持有相同值的副本,那么写入时复制仍然是一个巨大的胜利。

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

答案 1 :(得分:6)

写时复制和移动语义是完全不同的概念,每个概念都有不同的用途。虽然有一个常见的用例:从一个函数返回一个对象,其中因为原文超出范围它实际上是一个移动,在一般情况下它们是不同的:

通过复制写入多个同时处于活动状态的对象可以共享内容。使用移动语义,只有一个对象具有特定时间点的内容。

与此相比,写入时复制在多线程环境中存在问题,因为可能有多个对象访问相同的数据(只读)和控制块(读/写),需要在线程安全的方式。