C++ 参考手册
- C++11
- C++14
- C++17
- C++20
- C++ 编译器支持情况表
- 独立与宿主实现
- C++ 语言
- C++ 关键词
- 预处理器
- C++ 标准库头文件
- 具名要求
- 功能特性测试 (C++20)
- 工具库
- std::apply
- 库特性测试宏 (C++20)
- 程序支持工具
- std::initializer_list
- 函数对象
- std::hash
- std::pair
- std::tuple
- std::optional
- std::any
- std::variant
- 格式化库 (C++20)
- std::integer_sequence
- std::exchange
- std::make_from_tuple
- std::launder
- std::to_chars
- std::from_chars
- std::as_const
- std::source_location
- 变参数函数
- std::bitset
- std::cmp_equal, cmp_not_equal, cmp_less, cmp_greater, cmp_less_equal, cmp_greater_equal
- std::in_range
- std::declval
- std::forward
- std::move
- std::move_if_noexcept
- std::chars_format
- std::piecewise_construct_t
- std::piecewise_construct
- std::in_place, std::in_place_type, std::in_place_index, std::in_place_t, std::in_place_type_t, std::in_place_index_t
- 注释
- 类型支持(基本类型、RTTI、类型特性)
- 概念库 (C++20)
- 错误处理
- 动态内存管理
- 日期和时间工具
- 字符串库
- 容器库
- 迭代器库
- 范围库 (C++20)
- 算法库
- 数值库
- 输入/输出库
- 文件系统库
- 本地化库
- 正则表达式库
- 原子操作库
- 线程支持库
- 实验性 C++ 特性
- 有用的资源
- 索引
- std 符号索引
- 协程支持 (C++20)
- C++ 关键词
std::move
定义于头文件 <utility>
|
||
template< class T > typename std::remove_reference<T>::type&& move( T&& t ) noexcept; |
(C++11 起) (C++14 前) |
|
template< class T > constexpr typename std::remove_reference<T>::type&& 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::move
所产生者的亡值之一)调用函数时,重载决议选择接受右值引用参数的版本(包含移动构造函数、移动赋值运算符及常规成员函数,如 std::vector::push_back )。若参数标识一个占有资源的对象,则这些重载拥有移动参数所保有的任何资源的选择,但不强求如此。例如,链表的移动构造函数可以复制指向表头的指针,并将 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() str.clear(); // OK , clear() 无前提
而且,以亡值参数调用的标准库函数可以假设该参数是到对象的唯一引用;若它从左值带 std::move
构造,则不进行别名检查。尤其是,这表明标准库移动运算符不进行自赋值检查:
std::vector<int> v = {2, 3, 3}; v = std::move(v); // 未定义行为
示例
运行此代码
#include <iostream> #include <utility> #include <vector> #include <string> int main() { std::string str = "Hello"; std::vector<std::string> v; // 使用 push_back(const T&) 重载, // 表示我们将带来复制 str 的成本 v.push_back(str); std::cout << "After copy, str is \"" << str << "\"\n"; // 使用右值引用 push_back(T&&) 重载, // 表示不复制字符串;而是 // str 的内容被移动进 vector // 这个开销比较低,但也意味着 str 现在可能为空。 v.push_back(std::move(str)); std::cout << "After move, str is \"" << str << "\"\n"; std::cout << "The contents of the vector are \"" << v[0] << "\", \"" << v[1] << "\"\n"; }
可能的输出:
After copy, str is "Hello" After move, str is "" The contents of the vector are "Hello", "Hello"
参阅
(C++11) |
转发一个函数实参 (函数模板) |
(C++11) |
若移动构造函数不抛出则获得右值引用 (函数模板) |
(C++11) |
将某一范围的元素移动到一个新的位置 (函数模板) |