13-为何需要移动语义
18.2.1 为何需要移动语义
先来看C++11之前的复制过程。假设有如下代码:
vector<string> vstr;
// build up a vector of 20,000 strings, each of 1000 characters
...
vector<string> vstr_copy1(vstr); // make vstr_copy1 a copy of vstr
vector和string类都使用动态内存分配,因此它们必须定义使用某种new版本的复制构造函数。为初始化对象vstr_copy1,复制构造函数vector
但这确实妥当吗?有时候答案是否定的。例如,假设有一个函数,它返回一个vector
vector<string> allcaps(const vector<string> & vs)
{
vector<string> temp;
// code that stores an all-uppercase version of vs in temp
return temp;
}
接下来,假设以下面这种方式使用它:
vector<string> vstr;
// build up a vector of 20,000 strings, each of 1000 characters
vector<string> vstr_copy1(vstr); // #1
vector<string> vstr_copy2(allcaps(vstr)); // #2
从表面上看,语句#1和#2类似,它们都使用一个现有的对象初始化一个vector
要实现移动语义,需要采取某种方式,让编译器知道什么时候需要复制,什么时候不需要。这就是右值引用发挥作用的地方。可定义两个构造函数。其中一个是常规复制构造函数,它使用const左值引用作为参数,这个引用关联到左值实参,如语句#1中的vstr;另一个是移动构造函数,它使用右值引用作为参数,该引用关联到右值实参,如语句#2中allcaps(vstr)的返回值。复制构造函数可执行深复制,而移动构造函数只调整记录。在将所有权转移给新对象的过程中,移动构造函数可能修改其实参,这意味着右值引用参数不应是const。