|
由于新的复制优化,避免了复制分配开销。 例如,在字符串向量中间插入字符串时,没有复制重新分配开销,只有一次移动,即使它会导致向量本身的增长。 这些优化也适用于其他操作:例如,对两个巨大的对象执行添加操作。 如何启用这些值操作优化? 编译器可以隐式启用它们,就像编译器自动生成复制构造函数一样。 但是,类必须通过在类定义中声明移动赋值和移动构造函数“选择加入”它们。 移动在适当的成员函数声明和定义移动构造函数和移动赋值方法中使用双与号 (&&) rvalue 引用。 还需要插入正确的代码,以从源对象中“窃取内容”。
如何确定是否需要启用移动操作? 如果你已经知道需要启用复制构造,你可能也希望启用移动构造,特别是它比深层副本便宜的情况。 但是,如果知道需要移动支持,这不一定意味着要启用复制操作。 后一种情况称为“仅移动类型”。 标准库中已有的示例是 unique_ptr。 顺便说一下,旧的 auto_ptr 已被弃用,并被 unique_ptr 取代,这正是由于以前版本的 C++ 中缺乏移动语义支持。
通过使用移动语义,可以按值返回或在中间插入。 移动是复制的优化。 无需将堆分配作为解决方法。 请看下面的伪代码:
C++
复制
#include <set>
#include <vector>
#include <string>
using namespace std;
//...
set<widget> LoadHugeData() {
set<widget> ret;
// ... load data from disk and populate ret
return ret;
}
//...
widgets = LoadHugeData(); // efficient, no deep copy
vector<string> v = IfIHadAMillionStrings();
v.insert( begin(v)+v.size()/2, "scott" ); // efficient, no deep copy-shuffle
v.insert( begin(v)+v.size()/2, "Andrei" ); // (just 1M ptr/len assignments)
//...
HugeMatrix operator+(const HugeMatrix& , const HugeMatrix& );
HugeMatrix operator+(const HugeMatrix& , HugeMatrix&&);
HugeMatrix operator+( HugeMatrix&&, const HugeMatrix& );
HugeMatrix operator+( HugeMatrix&&, HugeMatrix&&);
//...
hm5 = hm1+hm2+hm3+hm4+hm5; // efficient, no extra copies
|
|