命名空间
变体
操作

std::move

来自 cppreference.com
< cpp‎ | utility
 
 
实用程序库
语言支持
类型支持 (基本类型, RTTI)
库功能测试宏 (C++20)
动态内存管理
程序实用程序
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三路比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用实用程序
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (在 C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(C++14)
(C++11)
(C++11)
move
(C++11)
(C++17)
通用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
基本字符串转换
(C++17)
(C++17)

 
定义在头文件 <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 生成一个 右值表达式,它标识其参数 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)
将元素范围移动到新位置
(函数模板) [编辑]