std:: move
|
定义于头文件
<utility>
|
||
|
template
<
class
T
>
typename std:: remove_reference < T > :: type && move ( T && t ) noexcept ; |
(C++11 起)
(C++14 前) |
|
|
template
<
class
T
>
constexpr std:: remove_reference_t < T > && move ( T && t ) noexcept ; |
(C++14 起) | |
std::move
用于
指示
对象
t
可以被“移动”,即允许将资源从
t
高效地转移至另一对象。
具体而言,
std::move
会生成一个
xvalue表达式
,该表达式标识其参数
t
。它完全等价于转换为右值引用类型的
static_cast
操作。
目录 |
参数
| t | - | 待移动的对象 |
返回值
static_cast < typename std:: remove_reference < T > :: type && > ( t )
注释
接受右值引用参数的函数(包括
移动构造函数
、
移动赋值运算符
,以及常规成员函数如
std::vector::push_back
)在通过
重载决议
被调用时,会匹配
右值
实参(包括
纯右值
如临时对象,或
亡值
如通过
std::move
生成的对象)。若实参标识了资源持有对象,这些重载函数可以选择(但非必须)转移实参所持有的资源。例如,链表的移动构造函数可以复制指向链表头节点的指针,并在实参中存储
nullptr
,而无需重新分配和复制每个独立节点。
右值引用变量的名称是左值,必须转换为亡值才能绑定到接受右值引用参数的函数重载,这就是为什么移动构造函数和移动赋值运算符通常使用
std::move
:
// 简单移动构造函数 A(A&& arg) : member(std::move(arg.member)) // 表达式 "arg.member" 是左值 {} // 简单移动赋值运算符 A& operator=(A&& other) { member = std::move(other.member); return *this; }
一种例外情况是当函数参数类型为 转发引用 (形式上类似于类型模板参数的右值引用)时,此时应改用 std::forward 。
除非另有说明,所有被移动的标准库对象都会处于"有效但未指定的状态",这意味着该对象的类不变式仍然成立(因此没有前置条件的函数,例如赋值运算符,在对象被移动后仍可安全使用):
std::vector<std::string> v; std::string str = "example"; v.push_back(std::move(str)); // str 当前有效但状态未指定 str.back(); // 若 size() == 0 则行为未定义:back() 有前置条件 !empty() if (!str.empty()) str.back(); // 正确,empty() 无前置条件且 back() 前置条件已满足 str.clear(); // 正确,clear() 无前置条件
此外,以xvalue实参调用的标准库函数可以假定该实参是对象的唯一引用;如果它是通过
std::move
从左值构造而来,则不会进行别名检查。然而,标准库类型的自移动赋值保证将对象置于有效(但通常未指定)状态:
std::vector<int> v = {2, 3, 3}; v = std::move(v); // v的值是未指定的
示例
#include <iomanip> #include <iostream> #include <string> #include <utility> #include <vector> int main() { std::string str = "Salut"; std::vector<std::string> v; // 使用 push_back(const T&) 重载,这意味着 // 我们将承担复制 str 的成本 v.push_back(str); std::cout << "After copy, str is " << std::quoted(str) << '\n'; // 使用右值引用 push_back(T&&) 重载, // 这意味着不会复制字符串;而是将 str 的 // 内容移动至 vector 中。这样成本更低, // 但也意味着 str 现在可能为空 v.push_back(std::move(str)); std::cout << "After move, str is " << std::quoted(str) << '\n'; std::cout << "The contents of the vector are {" << std::quoted(v[0]) << ", " << std::quoted(v[1]) << "}\n"; }
可能的输出:
After copy, str is "Salut"
After move, str is ""
The contents of the vector are {"Salut", "Salut"}
参见
|
(C++11)
|
转发函数实参,并通过模板类型参数保持其值类别
(函数模板) |
|
(C++11)
|
若移动构造函数不抛出异常,则将实参转换为右值引用
(函数模板) |
|
(C++11)
|
将元素范围移动到新位置
(函数模板) |