2014-10-17 17 views
6

tôi đã cố gắng để làm một cái gì đó như:Có phải std :: move và std :: copy giống hệt nhau không?

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

Và nhận lỗi này:

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

Mà có vẻ khó hiểu với tôi. Điều tương tự cũng xảy ra nếu bạn sử dụng std::move. Có vẻ như GCC sử dụng nội bộ một hàm có tên là std::__copy_move_a di chuyển thay vì bản sao. Việc bạn sử dụng std::copy hoặc std::move có quan trọng không?


#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; 
} 
+0

lý do tại sao bạn tạo trình biến đổi di chuyển từ 's2.begin()'? –

Trả lời

5

std::move di chuyển các yếu tố nếu có thể, và các bản sao khác. std::copy sẽ luôn sao chép.

libstdC++ 's copy_move_a cũng có thông số mẫu _IsMove. Điều đó và các loại trình vòng lặp, nó đại diện cho một mẫu lớp __copy_move là một phần chuyên biệt cho các danh mục vòng lặp khác nhau, v.v. nhưng quan trọng nhất: Cho dù là move hay không. Một trong những chuyên ngành là

#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 

Mã của bạn thất bại trong việc biên dịch vì một lý do hoàn toàn khác nhau: Phạm vi thứ hai được đưa ra thông qua move_iterator s. Nếu bạn không quan tâm đến chúng, chúng sẽ trả về một tham chiếu rvalue cho đối tượng - và bạn không thể gán thứ gì đó cho xvalue của loại vô hướng.

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

Các std::move được ngầm bao gồm trong *__result và là chủng loại giá trị như nhau, có nghĩa là, một Xvalue.

Ví dụ của bạn,

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

nên hoạt động tốt.

16

std::move(a, b, c); là ngữ nghĩa giống với

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

nỗ lực của bạn để sử dụng chúng cả hai thất bại vì đối số thứ ba - các iterator đầu ra - nên không là một iterator di chuyển. Bạn đang lưu trữ vào trình lặp thứ ba, không di chuyển từ nó. Cả hai

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

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

nên làm những gì bạn muốn.

Các vấn đề liên quan