【问题标题】:Does a vector have to store the size twice?向量是否必须存储大小两次?
【发布时间】:2011-09-30 01:43:40
【问题描述】:

这是一个相当学术的问题,我意识到它对优化无关紧要,但这只是出于兴趣。

据我了解,当您调用new[size] 时,会分配额外的空间来存储分配数组的大小。这样当调用delete [] 时,就知道可以释放多少空间了。

我写的是我认为向量将如何大致实现:

#include <cstddef>

template <class T>
class Vector
{
public:
  struct VectorStorage
  {
    std::size_t size;
    T data[];
  };

  Vector(std::size_t size) : storage(new VectorStorage[size])
  {
    storage->size = size;
  }

  std::size_t size() 
  { 
    return storage->size; 
  }

  ~Vector() 
  { 
    delete[] storage; 
  }
private:
  VectorStorage* storage;
};

据我所知,size 被存储了两次。一旦直接进入VectorStorage 对象(因为它需要这样size() 函数才能工作),但又以编译器隐藏的方式,所以delete[] 可以工作。

似乎size 被存储了两次。是这种情况且不可避免,还是有办法确保大小只存储一次?

【问题讨论】:

  • 你公然无视rule of three。
  • 如赋值运算符?这只是一个示例,不是矢量的完整实现。

标签: c++ optimization memory-management vector new-operator


【解决方案1】:

std::vector 不分配内存; std::allocator,或者你给vector的任何分配器,都是分配内存的。分配器接口给出了要分配/解除分配的项目数,因此不需要实际存储它。

【讨论】:

  • 分配器有什么方法可以避免存储大小?
  • @Clinton:我不确定你在问什么。分配器可以为所欲为。它可以有一个私有堆。它可以使用直接的操作系统调用来获取堆块并管理内存本身。它可以为所欲为。
【解决方案2】:

向量通常不存储大小。通常的实现将指针保留在最后一个元素的末尾和分配内存的末尾,因为可以reserve 空间而不实际在其中存储元素。但是,没有标准的方法来访问 new 存储的大小(可能一开始就没有存储),因此通常需要一些重复。

【讨论】:

    【解决方案3】:

    是的。但这是编译器一无所知的堆分配器的实现细节。它几乎肯定与向量的容量不同,因为向量只对元素的数量感兴趣,而不是字节数。并且堆块往往会出于自身目的而产生额外的开销。

    【讨论】:

      【解决方案4】:

      你在错误的地方设置了大小——你将它与每个元素一起存储(通过 VectorStorage 数组),它还包含一个 T 数组(每个 VectorStorage 实例)。你真的想拥有像这样的数组中的数组?你也永远不会在你的析构函数中清理你的 T 数组。

      【讨论】:

      • Joe:我的意思是一个带有size_t 的结构,后跟一个大小为size 的T 数组。如何使用new 分配它?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-17
      • 2018-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多