使用unique_ptr并返回引用,或者我应该使用shared_ptr并在需要时制作副本

Use a unique_ptr and return a reference or should I use a shared_ptr and make copies if needed

本文关键字:ptr 副本 shared 我应该 引用 返回 unique 或者 使用      更新时间:2023-10-16

我有一个缓存,它将对象的唯一 ptrs 存储在无序映射中,并为缓存的用户返回对象的引用。它按预期工作,存储对象,直到它们超出范围。

缓存的实现方式如下:

将对象存储在缓存中:

template<typename T>
template<typename... Args>
void ResourceCache<T>::add(const std::string& name, Args... args)
{
m_cache->try_emplace(name, std::make_unique<T>(args...));
}

从缓存中获取对象:

template<typename T>
T& ResourceCache<T>::getCachedElement(const std::string& name) const
{
auto it = m_cache->find(name);
if(it != m_cache->end())
return *it->second;
throw "resource not found";
}

但是现在我遇到了一个问题,即引用并不总是我想从缓存中获取的,每个示例:

我有以下对象:

class GameObject
{
public:
void translate(const cheetah::Vector3f& position);
protected:
Quaternion m_rotation;
Vector3f m_position;
};

假设我希望对象具有纹理,目前对我来说唯一的方法是添加成员引用

Texture& m_texture

这将导致我不得不

  1. 将纹理传递给每个对象的构造函数,即使它们不需要纹理。
  2. 创建一个从游戏对象
  3. 继承的纹理游戏对象,并添加纹理成员和构造函数。
  4. 使用共享指针而不是唯一指针,并能够返回副本

现在我的问题是

在这种特定情况下,什么会被视为最佳实践? 我应该使用上述选项之一还是错过了更好的选项?

我知道我的问题不是最具体的,但我正在自己学习 c++,如果能得到别人对此的看法会很好。

假设ResourceCache持有Texture,这是我的想法。一般来说,似乎没有一个最好的解决方案。

  1. 将纹理传递给每个对象的构造函数,即使它们不需要纹理。
    • 你需要传递一个虚拟对象,所以如果你想用这种方式,我建议把它保留为原始指针
    • 通过这样做,您可以检查它是否真的有指针,因为它可以nullptr
    • 注意 无论是引用还是指针,都应确保ResourceCache的寿命超过所有GameObject- 必须手动管理生存期
  2. 创建一个从游戏对象
  3. 继承的纹理游戏对象,并添加纹理成员和构造函数。
    • 这可能是一种选择,但我认为这更像是一个设计问题
  4. 使用共享指针而不是唯一指针,并能够返回副本
    • 这将正常工作
    • 安全(没有双重删除/悬空指针等问题(
    • 共享指针具有开销