[英]Why is there no reallocation functionality in C++ allocators?
在 C 中,标准的内存处理函数是malloc()
、 realloc()
和free()
。 然而,C++ stdlib 分配器只并行其中两个:没有重新分配函数。 当然,不可能与realloc()
完全相同,因为简单地复制内存不适用于非聚合类型。 但是,比如说,这个函数会不会有问题:
bool reallocate (pointer ptr, size_type num_now, size_type num_requested);
在哪里
ptr
之前为num_now
对象分配了相同的分配器;num_requested
>= num_now
;和语义如下:
ptr
处的给定内存块从num_now
对象的大小num_now
到num_requested
对象,它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
不能完全改变内存大小的分配器只能通过无条件return false;
实现这样的功能return false;
.
是否有如此少的具有重新分配能力的分配器实现,以至于不值得打扰? 还是我忽略了一些问题?
来自: http : //www.sgi.com/tech/stl/alloc.html
这可能是最有问题的设计决策。 提供一个重新分配的版本可能会更有用一些,该版本可以在不复制的情况下更改现有对象的大小或返回 NULL。 这将使其直接适用于具有复制构造函数的对象。 在原始对象未完全填充的情况下,它还可以避免不必要的复制。
不幸的是,这将禁止使用 C 库中的 realloc。 这反过来又会增加许多分配器实现的复杂性,并使与内存调试工具的交互更加困难。 因此我们决定反对这种选择。
这实际上是 Alexandrescu 用标准分配器指出的一个设计缺陷(不是运算符 new[]/delete[],而是最初用于实现 std::vector 的 stl 分配器,例如)。
realloc 的发生速度明显快于 malloc、memcpy 和 free。 但是,虽然可以调整实际内存块的大小,但它也可以将内存移动到新位置。 在后一种情况下,如果内存块由非 POD 组成,则所有对象都需要在重新分配后销毁和复制构造。
标准库需要适应这种可能性的主要事情是作为标准分配器公共接口的一部分的重新分配函数。 像 std::vector 这样的类当然可以使用它,即使默认实现是 malloc 新大小的块并释放旧块。 它需要是一个能够销毁和复制构造内存中的对象的函数,但如果这样做,它就不能以不透明的方式处理内存。 那里涉及到一些复杂性,需要更多的模板工作,这可能是标准库中省略它的原因。
std::vector<...>::reserve 是不够的:它解决了可以预期容器大小的不同情况。 对于真正可变大小的列表,realloc 解决方案可以使像 std::vector 这样的连续容器更快,特别是如果它可以处理内存块成功调整大小而不移动的 realloc 情况,在这种情况下,它可以省略调用 copy内存中对象的构造函数和析构函数。
您所要求的本质上是vector::reserve
作用。 如果没有对象的移动语义,就无法在不进行复制和销毁的情况下重新分配内存和移动对象。
我想这是上帝出错的地方之一,但我懒得写信给标准委员会。
数组分配应该有一个重新分配:
p = renew(p) [128];
或类似的东西。
由于 C++ 的面向对象性质,以及包含各种标准容器类型,我认为这只是与 C 相比,对方向内存管理的关注较少。我同意在某些情况下 realloc() 会很有用,但解决这个问题的压力很小,因为几乎所有产生的功能都可以通过使用容器来获得。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.