保持不可构造对象的向量

时间:2013-03-30 19:53:20

标签: c++ c++11

我有班级MyObject。它的所有实例都应该由MyObjectSet拥有,并且不应该在其他地方构建它。在MyObjectSet内,我使用std::vector<MyObject>来存储所有实例。

问题是,要使std::vector<MyObject>生效,MyObject的移动构造函数必须是公开的(仅std::vector<MyObject>作为{{1}的朋友添加是不够的})。

MyObject

但如果我将其公开,则可以从其他地方实例化class MyObject { MyObject(int n); friend class MyObjectSet; public: MyObject(MyObject&&) = default; // without this, it doesn't compile }; class MyObjectSet { std::vector<MyObject> MyObjects; public: MyObject& GetMyObject(int some_param); };

MyObject

有什么方法可以解决这个问题吗?

可以在void SomeUnrelatedFunc(MyObjectSet& set) { MyObject m(std::move(set.GetMyObject(0))); // this shouldn't be possible } 内存储指向MyObject个实例的指针,但如果可能,我想避免这样做。

3 个答案:

答案 0 :(得分:2)

您需要将std::allocator<MyObject>声明为朋友:

class MyObject {

    MyObject(int n);
    friend class MyObjectSet;
    friend std::allocator<MyObject>;
};

然后使用vector::emplace_back()来实际构建对象。

class MyObjectSet {
    std::vector<MyObject> MyObjects;

public:
    MyObject& GetMyObject(int some_param)
    {
        MyObjects.emplace_back( some_param );
        return MyObjects.back();
    }
};

emplace_back()具有调用MyObject构造函数的作用,将some_param作为int参数传递给构造函数,并将创建的对象插入到列表的后面。构造调用是在std :: allocator中完成的,因此需要它的友谊。

答案 1 :(得分:0)

this post的已接受答案概述了类似问题的解决方法(涉及常规构造函数而不是移动构造函数)。也许你可以从那里采取一些想法?

答案 2 :(得分:0)

您可以创建自定义分配器并将其作为第二个参数传递给std::vector<>。使您的自定义分配器成为MyObject的朋友。你的自定义分配器不需要做任何特殊的事情 - 唯一的目的是以通常的方式分配MyObjects(例如使用new),同时通过成为朋友来访问私有构造函数。