一个不同的问题激发了以下想法:
增加容量时是否std::vector<T>
必须移动所有元素?
据我了解,标准行为是底层分配器请求新大小的整个块,然后移动所有旧元素,然后销毁旧元素,然后释放旧内存。
考虑到标准分配器接口,这种行为似乎是唯一可能的正确解决方案。但我想知道,修改分配器以提供一个reallocate(std::size_t)
返回 apair<pointer, bool>
并可以映射到底层的函数是否有意义realloc()
?这样做的好处是,如果操作系统实际上可以扩展分配的内存,那么根本不需要移动。布尔值将指示内存是否已移动。
(std::realloc()
可能不是最好的选择,因为如果我们不能扩展,我们不需要复制数据。所以实际上我们宁愿想要类似的东西extend_or_malloc_new()
。编辑:也许基于is_pod
-trait 的专业化可以让我们使用实际的realloc
,包括它的按位复制。只是一般情况下。)
这似乎是一个错失的机会。最坏的情况,你总是可以实现reallocate(size_t n)
as return make_pair(allocate(n), true);
,所以不会有任何惩罚。
是否有任何问题使此功能不适合或不适合 C++?
也许唯一可以利用这一点的容器是std::vector
,但话又说回来,这是一个相当有用的容器。
更新:一个小例子来澄清。当前resize()
:
pointer p = alloc.allocate(new_size);
for (size_t i = 0; i != old_size; ++i)
{
alloc.construct(p + i, T(std::move(buf[i])))
alloc.destroy(buf[i]);
}
for (size_t i = old_size; i < new_size; ++i)
{
alloc.construct(p + i, T());
}
alloc.deallocate(buf);
buf = p;
新实现:
pair<pointer, bool> pp = alloc.reallocate(buf, new_size);
if (pp.second) { /* as before */ }
else { /* only construct new elements */ }