【问题标题】:Why would you ever use heap allocation for objects you will reference through an std::vector?为什么你会为你将通过 std::vector 引用的对象使用堆分配?
【发布时间】:2021-11-06 21:37:51
【问题描述】:

我正在浏览来自this article about ECS-systems in game programming 的一些代码并试图理解它,我经常看到的是在似乎没有任何好处的地方使用堆内存。以此为例:

class ECS
{
public:
    void someFunction()
    {
        archetypes.push_back(new Archetype);
    }
    ~ECS()
    {
        for(Archetype* a : archetypes_)
        {
            delete a;
        }
    }
private:
    std::vector<Archetype*> archetypes_;
};

这是在代码中在内存中操作原型的唯一方法。这里也没有涉及多态性。堆上的原型似乎对代码没有影响,除了原型是由指针引用的事实。

为什么您会选择为此使用分配的内存?我经常在代码中看到这一点,在我看来,使用堆内存只是因为感觉是正确的做法,而不是真正考虑它是否适合它。 std::vector 已经在后台使用堆内存,所以当我们想要添加新原型时,为什么不直接将堆栈变量复制到向量中,并让向量处理分配?

class ECS
{
public:
    void someFunction()
    {
        archetypes.push_back(Archetype());
    }
private:
    std::vector<Archetype> archetypes_;
};

或者在这种情况下使用堆内存有正当理由吗?

【问题讨论】:

  • 也许Archetype 是一个基本类型,你想支持多态。但在这种情况下,你会使用std::vector&lt;std::unique_ptr&lt;Archetype&gt;&gt;
  • 另一个可能的原因是如果对象是不可复制的,或者如果你想在不复制对象的情况下将对象的所有权移入和移出向量(尽管在 c+11 和更高版本中你在大多数情况下可以使用 move-assignment 来获得相同的效果)
  • Pimpl 成语可能是一个原因。您将ECS 代码与Archetype 代码解耦。
  • @rturrado 通常你会将外观类型的实例放入一个向量中,除了外观之外没有人应该知道 pimpl 指针。
  • 代码分发Archetype*指针,例如在Archetype* ECS::GetArchetype(const ArchetypeID&amp; id)。如果您有std::vector&lt;Archetype&gt;,并分发了一个指向其元素的指针,那么如果稍后将另一个原型添加到向量中,则该指针可能会变得无效。也许指针稳定性是作者所追求的。

标签: c++ heap-memory new-operator delete-operator


【解决方案1】:

明显的原因是您不希望在向量增长时移动/复制数据项,

这可能有几个原因,一个是移动/复制类型很昂贵(甚至不可能),另一个是您不希望指向单个原型的指针因向量的更改而失效,

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-10
    • 2010-09-12
    • 2011-06-10
    • 2016-10-02
    相关资源
    最近更新 更多