我有班级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
个实例的指针,但如果可能,我想避免这样做。
答案 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),同时通过成为朋友来访问私有构造函数。