你能把pimpl-Class放在一个向量中吗?

时间:2015-06-18 07:40:26

标签: c++ class c++11 smart-pointers

我有一个使用PImpl Ideom实现的类:

class FooImpl {};

class Foo
{
   unique_ptr<FooImpl> myImpl;
public:
   Foo();
   ~Foo();
};

现在我想将它放入std :: vector

void Bar()
{
   vector<Foo> testVec;
   testVec.resize(10);
}

但是当我这样做时,我得到编译器错误(VC ++ 2013)

  

错误C2280:'std :: unique_ptr&gt; :: unique_ptr(const std :: unique_ptr&lt; _Ty,std :: default_delete&lt; _Ty&gt;&gt;&amp;)':尝试引用已删除的函数

我在testVec.emplace_back();testVec.push_back(std::move(Foo()));

时遇到同样的错误

(作为一种解决方法,使用vector<unique_ptr<Foo>>似乎有效,但我不明白为什么上面的代码不起作用。)

工作示例:http://coliru.stacked-crooked.com/a/b274e1209e47c604

2 个答案:

答案 0 :(得分:2)

由于std::unique_ptr不可复制,因此类Foo没有有效的复制构造函数。

你可以deep copy or use a move constructor

#include <memory>
#include <vector>

class FooImpl {};

class Foo
{
   std::unique_ptr<FooImpl> myImpl;
public:
   Foo( Foo&& f ) : myImpl( std::move( f.myImpl ) ) {}
   Foo(){}
   ~Foo(){}
};

int main() {
    std::vector<Foo> testVec;
    testVec.resize(10);
    return 0;
}

实例:https://ideone.com/HYtPMu

答案 1 :(得分:2)

所以会发生vector模板尝试访问Foo类的复制构造函数。您尚未提供一个,因此编译器会尝试生成一个默认实现,该实现在所有成员上调用复制构造函数。由于std::unique_ptr没有来自另一个std::unique_ptr的复制构造函数(这是合乎逻辑的,因为它不知道如何复制对象),因此编译器无法为Foo生成赋值运算符失败。所以你可以做的是为Foo类提供一个拷贝构造函数,并决定如何处理指针:

#include <memory>
#include <vector>

using namespace std;
class FooImpl {};

class Foo
{
    unique_ptr<FooImpl> myImpl;
public:
    Foo()
    {
    }
    ~Foo()
    {
    }
    Foo(const Foo& foo)
    {
        // What to do with the pointer?
    }
    Foo& operator= (const Foo& foo)
    {
        if (this != &foo)
        {
            // What to do with the pointer?
        }
        return *this;
    }
};

int main(int argc, char** argv)
{
    vector<Foo> testVec;
    testVec.resize(10);
    return 0;
}