我有一个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() );
}
答案 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; }
};
由于在方法开始时需要一个新的临时文件,编译器将选择复制或移动构造函数来自行创建此临时文件,并且您不必同时编写复制赋值运算符和移动赋值运营商:)