为什么C++分配器中没有重新分配功能?

dou*_*lep 33 c++ memory-management realloc

在C中,标准内存处理函数是malloc(),realloc()free().但是,C++ stdlib分配器只兼容其中两个:没有重新分配功能.当然,不可能完全相同realloc(),因为简单地复制内存不适合非聚合类型.但是,这个函数是否会出现问题:

bool reallocate (pointer ptr, size_type num_now, size_type num_requested);
Run Code Online (Sandbox Code Playgroud)

哪里

  • ptr先前为num_now对象分配了相同的分配器;
  • num_requested> = num_now;

和语义如下:

  • 如果分配器可以ptr从给定num_now对象的大小扩展给定的内存块num_requested,它会这样做(留下额外的内存未初始化)并返回true;
  • 否则它什么都不做并返回false.

当然,这不是很简单,但据我所知,分配器主要用于容器和容器的代码通常很复杂.

给定这样的函数,std::vector比如说,可以增长如下(伪代码):

if (allocator.reallocate (buffer, capacity, new_capacity))
  capacity = new_capacity;     // That's all we need to do
else
  ...   // Do the standard reallocation by using a different buffer,
        // copying data and freeing the current one
Run Code Online (Sandbox Code Playgroud)

无法完全改变内存大小的分配器可以通过无条件实现这样的功能return false;.

是否有这么少的重新分配能力的分配器实现,它不值得打扰?还是有一些我忽略的问题?

5ou*_*und 19

来自:http: //www.sgi.com/tech/stl/alloc.html

这可能是最值得怀疑的设计决定.提供一个重新分配版本可能会更有用,它可以在不复制或返回NULL的情况下更改现有对象的大小.这将使它对具有复制构造函数的对象直接有用.在原始对象尚未完全填充的情况下,它也可以避免不必要的复制.

不幸的是,这会禁止使用C库中的realloc.这反过来会增加许多分配器实现的复杂性,并且会使与内存调试工具的交互更加困难.因此我们决定反对这种选择.

  • 我认为很遗憾他们至少没有为Allocator的界面添加重新分配方法.它可以实现为只释放现有块并分配一个新块,但它可能会在以后使用Allocator接口重做所有代码时实现新块. (3认同)
  • 令人遗憾的是,C 从不费心添加“方便时调整大小分配”功能,附带条件是允许符合要求的实现始终决定调整大小“不方便” (2认同)

sti*_*472 13

这实际上是Alexandrescu用标准分配器指出的设计缺陷(不是operator new []/delete [],而是最初用于实现std :: vector的stl分配器,例如).

realloc可以比malloc,memcpy和free更快地发生.但是,虽然可以调整实际内存块的大小,但它也可以将内存移动到新位置.在后一种情况下,如果内存块由非POD组成,则需要在realloc之后销毁所有对象并进行复制构造.

标准库需要适应这是一个最主要的可能是一个再分配的功能为标准分配的公共接口的一部分.像std :: vector这样的类当然可以使用它,即使默认实现是malloc新大小的块并释放旧块.它需要是一个能够在内存中销毁和复制构造对象的函数,但如果它这样做,它就不能以不透明的方式处理内存.这里有一点复杂性,需要更多的模板工作,这可能是它从标准库中省略的原因.

std :: vector <...> :: reserve是不够的:它解决了可以预期容器大小的不同情况.对于真正可变大小的列表,realloc解决方案可以使像std :: vector这样的连续容器更快,特别是如果它可以处理内存块成功调整大小而不被移动的realloc情况,在这种情况下它可以省略调用副本内存中对象的构造函数和析构函数.


Mar*_*som 8

你所要求的基本上是什么vector::reserve.没有对象的移动语义,就没有办法重新分配内存并移动对象而不进行复制和销毁.