Are std :: move and std :: copy the same?

I tried to do something like:

std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()), std::make_move_iterator(s2.begin())); 

And got this error:

 error: using xvalue (rvalue reference) as lvalue *__result = std::move(*__first); 

It seemed incomprehensible to me. The same thing happens if you use std::move . It seems that GCC internally uses a function called std::__copy_move_a , which moves, not copies. Does using std::copy or std::move matter?


 #include <string> #include <iostream> #include <algorithm> #include <iterator> #include <cstring> struct Test { typedef std::string::value_type value_type; std::string data; Test() { } Test(const char* data) : data(data) { } ~Test() { } Test(const Test& other) : data(other.data) { std::cout << "Copy constructor.\n"; } Test& operator=(const Test& other) { data = other.data; std::cout << "Copy assignment operator.\n"; return *this; } Test(Test&& other) : data(std::move(other.data)) { std::cout << "Move constructor.\n"; } decltype(data.begin()) begin() { return data.begin(); } decltype(data.end()) end() { return data.end(); } void push_back( std::string::value_type ch ) { data.push_back(ch); } }; int main() { Test s1("test"); Test s2("four"); std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()), std::make_move_iterator(s2.begin())); std::cout << s2.data; } 
+6
source share
2 answers

std::move(a, b, c); semantically identical

 std::copy(std::make_move_iterator(a), std::make_move_iterator(b), c); 

Your efforts to use them failed because the third argument - the output iterator - should not be an iterator of displacement. You store in the third iterator without going from it. Both

 std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()), s2.begin()); 

and

 std::move(s1.begin(), s1.end(), s2.begin()); 

should do what you want.

+16
source

std::move moves elements if possible, and copies otherwise. std::copy will always be copied.

libstdc ++ copy_move_a also accepts the _IsMove template _IsMove . These are the types of iterators, he delegates the template of the __copy_move class, which partially specializes for different categories of iterators, etc., But the most important thing: whether it is move or not. One of the specializations is

 #if __cplusplus >= 201103L template<typename _Category> struct __copy_move<true, false, _Category> // first specialized template argument is whether to move { template<typename _II, typename _OI> static _OI __copy_m(_II __first, _II __last, _OI __result) { for (; __first != __last; ++__result, ++__first) *__result = std::move(*__first); // That may be your line return __result; } }; #endif 

Your code cannot compile for a completely different reason: the second range is specified through move_iterator s. If you are looking for them, they return an rvalue reference to the object - and you cannot assign something the value x to a value of a scalar type.

 int i; std::move(i) = 7; // "expression not assignable" -- basically what your code does 

std::move implicitly included in *__result and has the same category of values, that is, the value of x.

In your example

 std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()), s2.begin()); 

should work fine.

+5
source

Source: https://habr.com/ru/post/976890/


All Articles