2014-10-17 152 views
6

我試着這樣做:std :: move和std :: copy是否一致?

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

而得到這個錯誤:

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

這似乎令人困惑了我。如果您使用std::move,則會發生同樣的情況。看來GCC內部使用了一個名爲std::__copy_move_a的函數,該函數移動而不是複製。無論您使用std::copy還是std::move,這都有影響嗎?


#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

你爲什麼要從s2.begin()'移動迭代器? – 2014-10-17 20:32:51

回答

5

std::move移動如果可能的元件,並且拷貝否則。 std::copy將始終複製。

libstdC++的copy_move_a也採用模板參數_IsMove。這和迭代器類型一樣,它委託給__copy_move類模板,該模板部分專用於不同的迭代器類別等,但最重要的是:是否爲move。 的特化的一個是

#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 

您的代碼不能編譯一個完全不同的原因是:該第二範圍是通過move_iterator給出:S。如果您取消引用它們,它們將返回一個對象的引用值 - 並且您不能將某些值分配給標量類型的xvalue。

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

std::move被隱式包括在*__result和是相同的值的類別,即,x值。

對於你的榜樣,

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

應該正常工作。

16

std::move(a, b, c);是語義上

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

你的努力,使用這兩個失敗,因爲第三個參數 - 輸出迭代 - 應該一招迭代器。你正在存儲到第三個迭代器中,而不是從它移動。無論

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

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

應該做你想要什麼。

相關問題