我注意到当包含类型包含unique_ptr时,无法删除向量的元素。
例如这个类:
class Bar
{
std::unique_ptr<int> pointerTest;
Bar(Bar &bar) {};
public:
Bar() { pointerTest = std::unique_ptr<int>(new int); }
Bar(Bar &&bar) { this->pointerTest = move(bar.pointerTest); }
void testFunc() { pointerTest.release(); }
};
这不适用于此用法:
int main()
{
vector<Bar> test123;
Bar foo;
test123.push_back(move(foo));
test123.erase(test123.begin());
}
//Error 1 error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 611 1 testing
当您只调用对象方法而不是擦除时,代码将起作用:
for (auto &item : test123)
item.testFunc();
为什么我不能在矢量上使用擦除的原因是什么?我怎么能解决这个问题呢?
答案 0 :(得分:3)
问题是你的班级没有正确遵守三/五的规则。您可以定义副本和移动构造函数,但不能定义移动赋值运算符。这意味着不会生成移动赋值运算符,并且在分配时始终使用默认的复制赋值运算符。但是,由于您的类具有不可复制的成员,因此默认的复制赋值运算符被定义为已删除,因此在使用时会出错。
并且它被调用,因为从向量中移除元素会导致向量的所有后续元素的移位(即赋值)。这通常是一个移动分配,但由于你的类没有定义(而不是自动生成),所以调用了复制赋值 - 并且失败了。
我看到你正在使用Visual Studio,因此无论如何都不会自动生成移动构造函数/移动赋值运算符(VS不支持此部分标准)。因此,要以VS兼容的方式修复此问题,请定义移动赋值运算符。当你在它的时候删除复制构造函数可能是一个好主意 - 该类看起来像一个不可复制的类的主要例子。
答案 1 :(得分:1)
来自g ++ 4.8.1的错误消息非常清楚:
garbage.cpp:9:11:注意:'Bar&amp; Bar :: operator =(const Bar&amp;)'是 隐式声明为已删除,因为'Bar'声明了一个移动 构造函数或移动赋值运算符
通过添加移动运算符,问题得以解决:
class Bar
{
std::unique_ptr<int> pointerTest;
Bar(const Bar &);
public:
Bar() { pointerTest = std::unique_ptr<int>(new int); }
Bar(Bar &&bar) : pointerTest( move(bar.pointerTest)) {}
Bar& operator=(Bar&& bar){ pointerTest = std::move(bar.pointerTest); return *this;}
void testFunc() { pointerTest.release(); }
};