当包含对象包含unique_ptr时,如何删除向量的元素?

时间:2013-11-22 15:31:20

标签: c++ vector visual-studio-2013 unique-ptr

我注意到当包含类型包含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();

为什么我不能在矢量上使用擦除的原因是什么?我怎么能解决这个问题呢?

2 个答案:

答案 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(); }
};