What is move_iterator for
What is move_iterator for
如果我理解正确,a=std::move(b)
将引用 a 绑定到 b 的地址。并且此操作后,b指向的内容无法保证。
这里的move_iterator
实现有这条线
auto operator[](difference_type n) const -> decltype(std::move(current[n]))
{ return std::move(current[n]); }
但是,我认为在数组中std::move
元素是没有意义的。如果a=std::move(b[n])
会怎样?
以下示例也让我感到困惑:
std::string concat = std::accumulate(
std::move_iterator<iter_t>(source.begin()),
std::move_iterator<iter_t>(source.end()),
std::string("1234"));
由于concat
本身将分配一个连续的内存块来存储结果,因此不会与source
有任何重叠。source
中的数据将复制到concat
但不会移动。
如果我理解正确,
a=std::move(b)
将引用a
绑定到b
的地址。 并且此操作后,b指向的内容无法保证。
啊,不:a
不一定是参考。 上述对std::move
的使用还授予编译器调用decltype(a)::operator=(decltype(b)&&)
(如果存在)的权限:在赋值期间使用此类赋值运算符a
不需要保留b
的值,但仍必须保留b
某种理智状态以供销毁。
但是,我认为在数组中
std::move
元素是没有意义的。如果a=std::move(b[n])
会怎样?
这是有道理的...这只是意味着每个数组元素可以有效地分配/移动到另一个变量,但每个元素只能分配一次。 从对象中移出后,正确编写的移动构造函数或赋值运算符应使对象处于有效但未指定的状态,这意味着您通常需要在读取对象之前再次设置它们。
我在这里的回答显示了有人如何将元素从list
追加/移动到vector
。 使用当前的C++标准,您可以像这样直接创建move_iterators。
下面的代码显示了 - 即使使用较旧的编译器/C++标准 - 如果您想从源迭代器范围内的元素移动,make_move_iterator
也可以与std::copy
一起使用。
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
struct X
{
X(int n) : n_(n) { }
X(const X& rhs) : n_(rhs.n_) { }
X(X&& rhs) : n_{ rhs.n_ } { rhs.n_ *= -1; std::cout << "=(X&&) "; }
X& operator=(X&& rhs) { n_ = rhs.n_; rhs.n_ *= -1; std::cout << "=(X&&) "; return *this; }
int n_;
};
int main()
{
std::vector<X> v{2, 1, 8, 3, 4, 5, 6};
std::vector<X> v2{};
std::copy(v.begin() + 2, v.end(), std::insert_iterator(v2, v2.end()));
for (auto& x : v)
std::cout << x.n_ << ' ';
std::cout << 'n';
std::copy(std::make_move_iterator(v.begin() + 2), std::make_move_iterator(v.end()), std::insert_iterator(v2, v2.end()));
for (auto& x : v)
std::cout << x.n_ << ' ';
std::cout << 'n';
}
输出:
2 1 8 3 4 5 6
=(X&&) =(X&&) =(X&&) =(X&&) =(X&&) 2 1 -8 -3 -4 -5 -6
代码可以在coliru上运行/编辑。
move_iterator
的目的是为算法提供其输入的右值。
您的示例auto a=std::move(b[n])
不会移动数组中的值,而是将其移出数组,这是明智的做法。
std::accumulate
诀窍是 std::string 的 operator+ 定义(请记住,累积的默认版本使用 operator+
。它对右值参数进行了特殊优化。对于我们的情况,重载数字 7 很重要,因为它accumulate
使用表达式 init + *begin
.这将尝试重用右侧参数的内存。如果这实际上被证明是一种优化,还不清楚。
http://en.cppreference.com/w/cpp/iterator/move_iterator 是这样说的:
std::move_iterator 是一个迭代器适配器,其行为与底层迭代器(必须至少是输入迭代器)完全相同,只是取消引用将底层迭代器返回的值转换为右值。
大多数(如果不是全部)标准算法接受范围,从范围的开头到结束遍历迭代器,并对取消引用的迭代器执行操作。例如,std::accumulate
可以实现为:
template <class InputIterator, class T>
T accumulate (InputIterator first, InputIterator last, T init)
{
while (first!=last) {
init = init + *first;
++first;
}
return init;
}
如果 first
和 last
是正常的迭代器(调用是
std::accumulate(source.begin(), source.end(), std::string("1234"));
,则*first
是对字符串的左值引用,表达式 init + *first
将调用 std::operator+(std::string const&, std::string const&)
(此处重载 1)。
但是,如果呼叫是
std::accumulate(std::make_move_iterator(source.begin()), std::make_move_iterator(source.end()), std::string("1234"));
然后在 std::accumulate 中,first
和 last
是移动迭代器,因此*first
是一个右值引用。这意味着init + *first
调用改为std::operator+(std::string const&, std::string &&)
(重载 7)。
- "error: no matching function for call to"构造函数错误
- 表示"accepting anything for this template argument" C++概念的通配符
- 如何在C++中从两个单独的for循环中添加两个数组
- 在Linux for Windows上编译C++代码时出错
- 调用专用模板时出错"no matching function for call to [...]"
- 为什么我的for循环不能正确获取argv
- 为什么我不能在 FOR LOOP 中使用 i/10,C++?
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 在基于范围的for循环中使用结构化绑定声明
- 通过for循环使用用户输入填充列表
- 使用for循环检查数组中的重复项
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 正在使用for循环创建QScatterSerie
- Python中的for循环与C++有何不同
- std::memory_order for std::atomic:<T>:wait
- 在更改for循环的第三部分后,未使用for循环结果
- 在 for 循环中查找问题时遇到困难
- 嵌套for循环C++的问题(初学者)
- using vs. typedef for std::vector::iterator