Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is move_iterator for

If I understand it correct, a=std::move(b) binds reference a to the address of b. And after this operation the content that b points to is not guaranteed.

The implementation of move_iterator here has this line

auto operator[](difference_type n) const -> decltype(std::move(current[n]))   { return std::move(current[n]); } 

However, I don't think it makes sense to std::move an element in an array. What happens if a=std::move(b[n])?

The following example confuses me also:

std::string concat = std::accumulate(                              std::move_iterator<iter_t>(source.begin()),                              std::move_iterator<iter_t>(source.end()),                              std::string("1234")); 

Since the concat will itself allocate a continuous chunk of memory to store the result, which will not have any overlap with source. The data in source will be copied to concat but not moved.

like image 547
Min Lin Avatar asked Jan 20 '15 10:01

Min Lin


People also ask

What is a move iterator?

std::move_iteratorIf this iterator is used as an input iterator, the effect is that the values are moved from, rather than copied from.

How do you advance an iterator in C++?

std::advance in C++ std::advance advances the iterator 'it' by n element positions. Syntax : template void advance (InputIterator& it, Distance n); it : Iterator to be advanced n : Number of element positions to advance. This shall only be negative for random-access and bidirectional iterators.


1 Answers

If I understand it correct, a=std::move(b) binds reference a to the address of b. And after this operation the content that b points to is not guaranteed.

Ah, no: a is not necessarily a reference. The above use of std::move also grants the compiler permission to call decltype(a)::operator=(decltype(b)&&) if it exists: such assignment operators are used when during the assignment to a the value of b need not be preserved, but b must still be left in some sane state for destruction.

However, I don't think it makes sense to std::move an element in an array. What happens if a=std::move(b[n])?

It can make sense... it just means that each array elements may be efficiently assigned/moved to another variable, but only once per element. After they've been moved-from, a properly-written move constructor or assignment operator should leave objects in a valid but unspecified state, which means you'd usually want to set them again before reading from them.

My answer here shows how someone could append/move elements from a list to a vector. With current C++ Standards, you can create move_iterators directly like that.

The code below shows how - even with older compilers / C++ Standards - make_move_iterator can be used with std::copy if you want to move from the elements in the source iterator range.

#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'; } 

Output:

2 1 8 3 4 5 6  =(X&&) =(X&&) =(X&&) =(X&&) =(X&&) 2 1 -8 -3 -4 -5 -6  

Code can be run / edited on coliru.

like image 177
Tony Delroy Avatar answered Sep 19 '22 05:09

Tony Delroy