我有一个类ResourceManifest
,它从文件中加载3d模型并将它们保存在向量中,然后根据请求将它们移出。也可以从存储中删除缓存的3dmodel,我希望我的其他组件在发生这种情况时能够意识到这一点。这是我现在拥有的,但它不能满足我对属于ResourceManifest
类的唯一所有权的意图
typedef boost::shared_ptr<Model> ModelPtr;
class ResourceManifest
{
public:
ResourceManifest(IRenderer& renderer);
~ResourceManifest();
ModelPtr LoadModel(const std::string& modelName, const std::string& assetName);
ModelPtr GetModel(const std::string& modelName);
void DeleteModel(ModelPtr model);
private:
IRenderer& mRenderer;
std::vector<ModelPtr> mModels;
IMemoryAllocator& mMemoryAllocator;
};
在我的第一次尝试中,我将Model
保留为shared_ptrs;但结果是,如暗示的那样,它是共享所有权,我只希望ResourceManifest
向量内的副本成为所有者。我想要一个智能指针的原因只是能够查询Model
是否仍然存在,这是我用原始指针做不到的事情。
我知道weak_ptr,但如果可能,我宁愿避免使用它的语法;如果可能,我想像普通指针一样使用它,就像这样......
ModelPtr modelCube = resourceManifest.GetModel("Cube");
...... later on
if (modelCube)
modelCube->render();
答案 0 :(得分:1)
您可以为weak_ptr
创建自己的包装器。这是一个简单的,未完成的,可以帮助你入门。
template<typename T>
class weak_ptr2
{
public:
weak_ptr2(std::shared_ptr<T> const & sp)
:wp(sp)
{}
T & operator*() const { return *(wp.lock()); }
T * operator->() const { return wp.lock().get(); }
explicit operator bool() const { return !wp.expired(); }
private:
std::weak_ptr<T> wp;
};
答案 1 :(得分:1)
解决问题的一个解决方案是使用weak_ptr,但正如我理解你的问题,你不喜欢它的语法。 ResourceManifest :: GetModel将返回一个weak_ptr,你必须使用.lock()才能获得一个shared_ptr到Model,如果.lock()成功,则会产生一个你可以使用的有效shared_ptr。
您在问题中未提及的shared_ptr / weak_ptr方法的另一个问题是,尽管除了weak_ptr之外没有提供任何内容,ResourceManifest实际上并不是模型的所有者。我的意思是没有任何东西阻止ResourceManifest的用户将weak_ptr提升为shared_ptr并保持shared_ptr,从而使其保持活动的时间超过ResourceManifest想要的时间。简而言之,ResourceManifest无法控制模型的生命周期。
你可以做的是发明你自己的智能指针,它只保留原始指针:
MySmartPtr model = manifest.GetModel("foobar");
如果原始指针有效,则实现布尔测试:
if (model)
如果指针有效,您的智能指针可以询问ResourceManifest。如果指针有效,用户可以通过智能指针的解引用运算符使用指针:
model->render();
这里有一个问题:如果要从多个线程使用智能指针和ResourceManifest,那么
if (model)
model->render();
成为竞争条件,但由于你的问题没有提及多个主题,我不会为你提供答案......