GCC C++ 11删除移动可分配类的副本分配崩溃了std :: sort?

use*_*078 2 c++ gcc c++11

我正在尝试对实现移动赋值运算符的类的向量进行排序.此代码适用于Microsoft和Intel C++.在GCC 4.8.1中,复制构造函数被删除,似乎导致问题.

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
Run Code Online (Sandbox Code Playgroud)

在Matthieu M.的帮助下,此页面解释了为什么删除了复制构造函数.

#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;
}
Run Code Online (Sandbox Code Playgroud)

mas*_*oud 5

声明移动构造函数或移动赋值运算符会删除默认的复制/移动构造函数(IMO因为鼓励我们遵守5的规则!),另一方面std::sort需要move-construct或copy-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);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

要解决这个问题:

你需要一个可移动构造的类,你可以测试它is_move_constructible,std::sort需要第一个.使用move-constructor使其可移动构造.

您至少需要一个用于赋值的移动赋值或复制赋值,以及至少一个用于构造的复制构造函数或移动构造函数.

虽然你的类名是MoveOnly,我认为选择move-assignment和move-constructor是合理的.所以,这段代码足以编译:

class MoveOnly {

    ...

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

    MoveOnly& operator = (const MoveOnly && rhs) { ... }
};
Run Code Online (Sandbox Code Playgroud)