10

我有一个std::vector<Foo>whereFoo是一个包含Foo( Foo&& ) noexcept.

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

错误:使用已删除的函数 'Foobar& Foobar::operator=(const Foobar&)

编辑:当然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() );
}
4

3 回答 3

11

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

于 2012-09-28T09:54:14.993 回答
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);
}
于 2012-09-28T09:48:17.770 回答
1

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

struct Foo {
    Foo() {}

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

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

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

于 2012-09-28T10:11:15.303 回答