C++ 处理容器中的唯一\u ptr

C++ 处理容器中的唯一\u ptr,c++,c++11,smart-pointers,unique-ptr,C++,C++11,Smart Pointers,Unique Ptr,我有一个独特的向量,指向模型、网格等,如下所示: std::vector<std::unique_ptr<Model>> mLoadedModels; std::vector mloaddemdodels; 我选择unique_ptr是因为它会在向量析构函数上自动释放数据,也因为稍后如果我需要重新加载所有模型(由于OpenGL上下文的破坏/创建),我可以在我的资源管理器reset()中内部将其指向一个新的模型实例,而不会影响系统的其余部分 但我的问题是,如何与其他系统

我有一个独特的向量,指向模型、网格等,如下所示:

std::vector<std::unique_ptr<Model>> mLoadedModels;
std::vector mloaddemdodels;
我选择unique_ptr是因为它会在向量析构函数上自动释放数据,也因为稍后如果我需要重新加载所有模型(由于OpenGL上下文的破坏/创建),我可以在我的资源管理器reset()中内部将其指向一个新的模型实例,而不会影响系统的其余部分

但我的问题是,如何与其他系统共享向量的内容?您不能只传递唯一的\u ptr,因为这会改变所有权(由于其唯一的\u ptr),我希望在资源管理器中拥有唯一的所有权

我提出的解决方案如下,将访问封装在以下结构中:

template<typename T>
struct Handle
{
    Handle(std::unique_ptr<T>& resource) : mResource(resource)
    {
    }

    T& operator*()                  { return mResource.get(); }
    const T& operator*() const      { return mResource.get(); }
    T* operator->()                 { return mResource.get(); }
    const T* operator->() const     { return mResource.get(); }


private:
    std::unique_ptr<T>& mResource;
};

typedef Handle<Model> ModelPtr;

ModelPtr GetModel(const std::string& modelName);

// example:
ModelPtr monkey = GetModel("Monkey");
monkey->dance();

// reload resources, and then monkey dereferences to the new Model instance 
模板
结构句柄
{
句柄(std::unique_ptr&resource):mResource(resource)
{
}
运算符*(){return mResource.get();}
常量T&运算符*()常量{return mResource.get();}
T*运算符->(){return mResource.get();}
常量T*运算符->()常量{return mResource.get();}
私人:
std::独特的ptr和MRE资源;
};
typedef句柄模型ptr;
modelptrgetmodel(const std::string和modelName);
//例如:
ModelPtr monkey=GetModel(“monkey”);
猴子->舞蹈();
//重新加载资源,然后取消对新模型实例的引用

虽然这感觉有点噱头,但肯定有更好、更直接的解决方案吗?

有一个简单的解决方案

传递
vec[n].get()
——原始指针。只要你不储存它们,并且总是从所有者那里取回它们,并且所有者在你使用它们时不销毁它们,你就安全了

如果您不愿意遵守这一级别的规程,您需要的是
std::shared_ptr
vector
中,传递并存储
std::weak_ptr
s。当最后一个
共享的
消失时,
弱的
将自动失效(根据策略,唯一持久的
共享的
是拥有的
向量中的一个

这有一个附加的优点,如果你在一个元素上工作,而向量 >清除它自己,你就不会出错。您可以通过

.lock()
访问
弱\u ptr
,它返回一个
共享的\u ptr
,在其生存期内,原始指针保证是良好的


缺点是这会增加成本,优点是它允许弱共享所有权和延迟无效通知。

使用普通的
std::vector
并向各个元素分发原始指针。除非您需要动态多态性或期望对模型的引用超过向量的寿命,否则不需要将其变得更复杂。

如果您需要共享所有权,请使用
shared\u ptr
。然后,您可以将
弱ptr
s分发给观察者。
句柄
显然应该命名为
唯一ptr
。别开玩笑了,当向量调整大小时,你的
句柄将无效。分发原始
模型*
有什么不对?@Casey真的,它应该是
共享的独特的ptr
来处理生命问题(我的孩子)。@Yakk我喜欢使用
共享的独特的ptr*
来覆盖我所有的基础。不过我确实需要存储它们,例如,我的模型存储一个MeshPtr和一个MaterialPtr,等等。我想让它也像指针一样透明,使用弱ptr,每次你想访问资源时都必须执行lock(),对吗?先传递一个vec,然后是一个索引号,用句柄“`@KaiserJohaan”这样的结构包装,很少有理由将引用存储在持久对象中。第二,如果指针在任何一点上都无效,“作为指针透明”是不好的
.lock()
定义了一个作用域,在该作用域中指针不能无效且可以安全使用。如果你能证明所讨论的指针只会在某些点被销毁,那就太过分了……没有好的替代方法可以避免每次访问它时都必须执行.lock()。@kaiserjohaan sure:制定合理的生存期和访问规则。拥有它的人提供了它,而销毁发生在与非拥有指针生命周期不重叠的已知时间。如果
std::vector
调整大小,则指向
Model
的指针将失效,因此它们无法在任何可能修改
std::vector
长度的代码上持久存在@Yakk-Ah-yes,这太容易忘记了。现在,根据容器的操作方式,
std::deque
可能是合适的,但可能
std::unique\u ptr
/
get
解决方案是最好的。