std::move_iterator
在头文件 <iterator> 中定义 |
||
template< class Iter > class move_iterator; |
(自 C++11 起) | |
std::move_iterator
是一个迭代器适配器,其行为与底层迭代器完全相同(底层迭代器必须至少是 LegacyInputIterator 或模型 input_iterator
(自 C++20 起),或更强的迭代器概念(自 C++23 起)),不同之处在于解除引用将底层迭代器返回的值转换为右值。如果此迭代器用作输入迭代器,则其效果是将值从源移出,而不是从源复制。
内容 |
[编辑] 嵌套类型
名称 | 定义 | ||||
iterator_type
|
Iter
| ||||
iterator_category (条件存在) |
| ||||
iterator_concept (自 C++20 起) |
| ||||
value_type
|
| ||||
difference_type
|
| ||||
pointer
|
Iter
| ||||
reference
|
|
[编辑] 数据成员
名称 | 定义 |
current |
底层迭代器,base() 从中复制 或移动(自 C++20 起)(仅用于说明的成员对象*) |
[编辑] 成员函数
(C++11) |
构造一个新的迭代器适配器 (公有成员函数) |
(C++11) |
为另一个迭代器适配器赋值 (公有成员函数) |
(C++11) |
访问底层迭代器 (公有成员函数) |
(C++11)(C++11)(C++20 中已弃用) |
访问指向的元素 (公有成员函数) |
(C++11) |
通过索引访问元素 (公有成员函数) |
递增或递减迭代器 (公有成员函数) |
[编辑] 非成员函数
(C++11)(C++11)(C++20 中已删除)(C++11)(C++11)(C++11)(C++11)(C++20) |
比较底层迭代器 (函数模板) |
比较底层迭代器和底层哨兵 (函数模板) | |
(C++11) |
递增迭代器 (函数模板) |
(C++11) |
计算两个迭代器适配器之间的距离 (函数模板) |
计算底层迭代器和底层哨兵之间的距离 (函数模板) | |
(C++20) |
将解引用底层迭代器结果强制转换为其关联的右值引用类型 (函数) |
(C++20) |
交换两个底层迭代器指向的对象 (函数模板) |
(C++11) |
创建一个从参数推断类型的 std::move_iterator (函数模板) |
[编辑] 辅助模板
template< class Iterator1, class Iterator2 > requires (!std::sized_sentinel_for<Iterator1, Iterator2>) |
(自 C++20 起) | |
如果底层迭代器不满足该概念,则 std::disable_sized_sentinel_for
的此部分特化将阻止 move_iterator
的特化满足 sized_sentinel_for
。
[编辑] 注释
功能测试 宏 | 值 | Std | 功能 |
---|---|---|---|
__cpp_lib_move_iterator_concept |
202207L | (C++23) | 使 std::move_iterator<T*> 成为随机访问迭代器 |
[编辑] 示例
#include <algorithm> #include <iomanip> #include <iostream> #include <iterator> #include <ranges> #include <string> #include <string_view> #include <vector> void print(const std::string_view rem, const auto& v) { std::cout << rem; for (const auto& s : v) std::cout << std::quoted(s) << ' '; std::cout << '\n'; }; int main() { std::vector<std::string> v{"this", "_", "is", "_", "an", "_", "example"}; print("Old contents of the vector: ", v); std::string concat; for (auto begin = std::make_move_iterator(v.begin()), end = std::make_move_iterator(v.end()); begin != end; ++begin) { std::string temp{*begin}; // moves the contents of *begin to temp concat += temp; } // Starting from C++17, which introduced class template argument deduction, // the constructor of std::move_iterator can be used directly: // std::string concat = std::accumulate(std::move_iterator(v.begin()), // std::move_iterator(v.end()), // std::string()); print("New contents of the vector: ", v); print("Concatenated as string: ", std::ranges::single_view(concat)); }
可能的输出
Old contents of the vector: "this" "_" "is" "_" "an" "_" "example" New contents of the vector: "" "" "" "" "" "" "" Concatenated as string: "this_is_an_example"
[编辑] 缺陷报告
以下行为更改缺陷报告已追溯应用于以前发布的 C++ 标准。
DR | 应用于 | 发布的行为 | 正确行为 |
---|---|---|---|
LWG 2106 | C++11 | 解引用 move_iterator 可能会返回悬空引用如果解引用底层迭代器返回右值 |
返回 对象本身 |
LWG 3736 | C++20 | move_iterator 缺少 disable_sized_sentinel_for 特化 |
添加了 |
P2259R1 | C++20 | 成员 iterator_category 已定义,即使std::iterator_traits<Iter>::iterator_category 未定义 |
iterator_category 为在此情况下未定义 |
[编辑] 另请参阅
(C++11) |
创建一个从参数推断类型的 std::move_iterator (函数模板) |
(C++20) |
std::move_iterator 的哨兵适配器 (类模板) |