std::move
定义于头文件 <utility> |
||
template< class T > typename std::remove_reference<T>::type&& move( T&& t ) noexcept; |
(since C++11) (until C++14) |
|
template< class T > constexpr std::remove_reference_t<T>&& move( T&& t ) noexcept; |
(since 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
// Simple move constructor A(A&& arg) : member(std::move(arg.member)) // the expression "arg.member" is lvalue {} // Simple move assignment operator 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 is now valid but unspecified str.back(); // undefined behavior if size() == 0: back() has a precondition !empty() if (!str.empty()) str.back(); // OK, empty() has no precondition and back() precondition is met str.clear(); // OK, clear() has no preconditions
此外,使用将亡值参数调用的标准库函数可以假定该参数是对对象的唯一引用;如果它是从带有 std::move
的左值构造的,则不进行别名检查。但是,标准库类型的自移动赋值保证将对象置于有效(但通常未指定)的状态
std::vector<int> v = {2, 3, 3}; v = std::move(v); // the value of v is unspecified
[编辑] 示例
#include <iomanip> #include <iostream> #include <string> #include <utility> #include <vector> int main() { std::string str = "Salut"; std::vector<std::string> v; // uses the push_back(const T&) overload, which means // we'll incur the cost of copying str v.push_back(str); std::cout << "After copy, str is " << std::quoted(str) << '\n'; // uses the rvalue reference push_back(T&&) overload, // which means no strings will be copied; instead, the contents // of str will be moved into the vector. This is less // expensive, but also means str might now be empty. 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) |
将一系列元素移动到新位置 (函数模板) |