std :: vector :: erase()不想移动

时间:2012-09-28 09:40:22

标签: c++ c++11 move

我有一个std::vector<Foo>,其中Foo是一个包含Foo( Foo&& ) noexcept的类。

向容器添加对象可以完美地工作,但是使用std::vector::erase( iterator )删除它们不会,GCC 4.7会尝试调用我已删除的赋值运算符。确切的错误消息是:

错误:使用已删除的功能'Foobar&amp; Foobar :: operator =(const Foobar&amp;)

编辑:当然std::vector调用赋值运算符,而不是复制构造函数(您也可以在错误消息中看到)。在说明中修正了,抱歉。

以下是请求的示例源代码:

#include <vector>

class Foo {
    public:
        Foo() {}
        Foo( Foo&& other ) noexcept {}

        Foo( const Foo& ) = delete;
        Foo& operator=( const Foo& ) = delete;
};

int main() {
    std::vector<Foo> v;

    v.push_back( Foo{} );
    v.erase( v.begin() );
}

3 个答案:

答案 0 :(得分:11)

问题是您没有提供移动赋值运算符。这是某些函数的向量Movable要求的一部分。

答案 1 :(得分:2)

我无法重现它。结果是良好的习惯有很长的路要走:我已经定义了移动对齐运算符。

在GCC 4.7.2上生活:http://liveworkspace.org/code/36c600c285f2c91649fd4f73784c2c00

#include <iostream>
#include <vector>

struct Foo
{
    Foo() {}

    Foo(Foo const&) = delete;
    Foo(Foo&&) throw() { }

    Foo& operator=(Foo const&) = delete;
    Foo& operator=(Foo&&) throw() { return *this; }
};

int main(int argc, char* args[])
{
    std::vector<Foo> v;
    v.emplace_back();
    v.emplace_back();
    v.emplace_back();
    v.emplace_back();

    auto it = v.begin();
    it++;
    v.erase(it);
}

答案 2 :(得分:1)

DeadMG的答案非常好,但是我想推广另一种编写赋值运算符的方法:

struct Foo {
    Foo() {}

    Foo(Foo const&) = delete;
    Foo(Foo&&) throw() { }

    Foo& operator=(Foo) throw() { return *this; }
};

由于在方法开始时需要一个新的临时文件,编译器将选择复制或移动构造函数来自行创建此临时文件,并且您不必同时编写复制赋值运算符和移动赋值运营商:)