2013-09-27 72 views
2

我想排序實現移動賦值運算符的類的向量。此代碼在Microsoft和Intel C++中正常工作。在GCC 4.8.1中,複製構造函數被刪除,似乎導致問題。GCC C++ 11刪除移動賦值類的拷貝賦值崩潰std :: sort?

c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_algo.h:2164:11: error: use of deleted function 'constexpr MoveOnly::MoveOnly(const MoveOnly&)' 
__val = _GLIBCXX_MOVE(*__i); 
     ^
test.cpp:6:11: note: 'constexpr MoveOnly::MoveOnly(const MoveOnly&)' is implicitly declared as deleted because 'MoveOnly' declares a move constructor or move assignment operator 

,並與馬修M.幫助,this page解釋了爲什麼拷貝構造函數被刪除。

#include <vector> 
#include <algorithm> 
#include <iostream> 
#include <type_traits> 

class MoveOnly { 

public: 
    int data; 
    MoveOnly& operator = (const MoveOnly && rhs) { 
     data = rhs.data; 
     return *this; 
    } 
    MoveOnly& operator = (const MoveOnly & rhs) { 
     data = rhs.data; 
     return *this; 
    } 
    bool operator < (const MoveOnly& j) const { 
     return data<j.data; 
    } 
}; 

int main() { 

    std::cout<<"Is move_assignable:"<<std::is_move_assignable<MoveOnly>::value<<std::endl; 
    std::cout<<"Is copy_assignable:"<<std::is_copy_assignable<MoveOnly>::value<<std::endl; 
    std::vector<MoveOnly> vMoveOnly; 
    //std::sort(vMoveOnly.begin(), vMoveOnly.end()); 
    return 0; 
} 
+4

這不是崩潰,這是一個編譯錯誤。 –

+0

您是否嘗試添加複製構造函數? –

+0

@Kiril權利不會崩潰。對不起我的英語不好。 – user1662078

回答

5

聲明一個移動構造函數或移動賦值操作符刪除默認的複製/移動 構造(IMO由於鼓勵我們要遵守五個規則!),而另一方面std::sort需要移動的構建或複製的一個-construct有這個代碼:

template<typename _RandomAccessIterator> 
    void 
    __insertion_sort(_RandomAccessIterator __first, 
      _RandomAccessIterator __last) 
    { 
     if (__first == __last) 
    return; 

    for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) 
    { 
     if (*__i < *__first) 
     { 
      typename iterator_traits<_RandomAccessIterator>::value_type 
     __val = _GLIBCXX_MOVE(*__i); 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

要解決此問題:

你需要一個類,這是布展施工的你可以通過is_move_constructible,std::sort測試它需要第一個。放置一個移動構造器以使其可移動構建。

您至少需要移動分配或複製分配中的至少一個以進行賦值,並且至少需要複製構造函數或移動構造函數之一才能進行構造。

雖然您的課程名稱是MoveOnly,但我認爲選擇移動分配和移動構造函數是合理的。所以,這個代碼就足以編譯:

class MoveOnly { 

    ... 

    MoveOnly(MoveOnly &&m) : data(m.data) {} 

    MoveOnly& operator = (const MoveOnly && rhs) { ... } 
}; 
+1

@ user1662078:刪除它是正確的,標準強制它,請參閱http://stackoverflow.com/q/18895784/147192 –

+0

@MatthieuM。感謝參考頁面。雖然移動賦值操作符有點奇怪,但是我丟失了拷貝構造函數。 – user1662078

+1

@ user1662078:基本的答案是,只要你開始干預拷貝構造,拷貝分配或破壞,你正在做一些特殊的事情,很可能是默認生成的方法會**錯**。在C++ 03中,很多人都被咬了,所以這個缺陷在C++ 11中得到了解決,並且爲了促進交易,你總是可以編寫'X(X const&)= default;'如果你知道缺省值是好的* *。但至少這是一個有意識的決定,而不是疏忽。 –

-3

我添加了一些東西,你的代碼,並能正常工作:

#include <vector> 
#include <algorithm> 
#include <iostream> 
#include <type_traits> 

class MoveOnly { 

public: 
    int data; 
     MoveOnly (int i): 
     data (i) 
     {} 

    MoveOnly (MoveOnly && rhs): 
     data (std::move(rhs.data)) 
     {} 
    MoveOnly (const MoveOnly & rhs)=delete; 

    MoveOnly& operator = (MoveOnly && rhs) { 
     data = std::move(rhs.data); 
     return *this; 
    } 
    MoveOnly& operator = (const MoveOnly & rhs) { 
     data = rhs.data; 
     return *this; 
    } 
    bool operator < (const MoveOnly& j) const { 
     return data<j.data; 
    } 
}; 

int main() { 

    std::cout<<"Is move_assignable:"<<std::is_move_assignable<MoveOnly>::value<<std::endl; 
    std::cout<<"Is copy_assignable:"<<std::is_copy_assignable<MoveOnly>::value<<std::endl; 
    std::vector<MoveOnly> vMoveOnly; 
    vMoveOnly.push_back(MoveOnly(10)); 
    vMoveOnly.push_back(MoveOnly(666)); 
    vMoveOnly.push_back(MoveOnly(-100)); 
    std::sort(vMoveOnly.begin(), vMoveOnly.end()); 
    for(std::size_t i=0;i<vMoveOnly.size();++i){std::cout<<vMoveOnly[i].data<<std::endl;} 
    return 0; 
} 

PS:使用常數R值基準是一種無稽之談因爲右值引用的主要目的是移動對象而不是複製它們。移動對象的狀態意味着修改。所以沒有const

+0

那麼,爲什麼它不使用默認的移動/複製構造函數? –

+1

這很好,它的工作原理。但是,如果沒有解釋爲什麼它起作用,那麼它沒有多大用處。 –

+1

除了這是錯的。你已經刪除了拷貝構造函數,但實現了拷貝分配?什麼?絕對是-1。 –

相關問題