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.
If I understand it correct,
a=std::move(b)
binds referencea
to the address ofb
. 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 ifa=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.