移动C ++ 11的语义是否会超越写时复制的习惯用法?

时间:2011-12-08 04:43:47

标签: c++ c++11 idioms

我可能会在这里感到困惑,但我明白的是:

  • COW将返回“假”副本,直到其中一个呼叫者想要进行一些修改。
  • Move Semantic将在所有情况下返回“假”副本。

因此,如果我的目的是拥有一个只需要读取而不需要更新的对象,那么我应该只等待C ++编译器中的移动语义支持?

我是对的吗?

谢谢:)

2 个答案:

答案 0 :(得分:6)

移动语义不会返回“假”副本。相反,在复制操作中,它授予copyee删除原始副本的权限。

一个激励性的例子可能是有益的:

std::vector<int> bigData;

// fill bigData

std::vector<std::vector<int> > listOfData;

listOfData.push_back(std::move(bigData));
// after this point, the contents of bigData are unspecified (however accessing it is _not_ undefined behavior)

如果没有移动语义,则需要复制bigData以将其插入到listOfData中,或者手动将swap()转换为listOfData中的新空向量。但是使用移动语义,由std::vector在新数据中复制时调用的push_back的rvalue-reference-constructor(又名移动构造函数)有权删除bigData的旧内容 - 因此,允许窃取bigData的内部指针并将bigData重置为空向量,例如。

移动语义通常比COW语义更快,因为它们不需要维护共享的只读数据的引用计数。但是,它们更受限制 - 您无法使用移动语义为数据创建多个引用计数别名,您可以轻松方便地在容器之间混洗数据。

另请注意,最近版本的GCC和Microsoft Visual C ++都支持rvalue引用和移动语义(GCC with --std=c++0x),因此没有理由不在今天开始使用它们。

答案 1 :(得分:0)

copy-on-write和move构造函数是不同的东西。

让我们谈谈COW实现广泛存在的字符串。假设你有支持COW和移动语义的字符串实现。那么请考虑以下代码:

cow::string foo() { return string("foo"); } // move CTOR is in effect here.

cow::string a = foo(); // move ctor in effect
cow::string b = a; // copy ctor in effect

ab这里将共享相同的分配字符序列。在这里

std::string foo() { return string("foo"); } // move CTOR is in effect here.

std::string a = foo(); // move ctor in effect
std::string b = a; // copy ctor in effect

ab将分配并保持两个不同的字符序列,使内存消耗加倍。