据我所知,C ++不支持C语言中的'realloc(void *,size_t)'这样的运算符。
但是,std :: vector应该有一个缓冲区来容纳数据,并且应该扩展或压缩缓冲区。
然后如何在没有'realloc'函数的情况下调整std :: vector缓冲区的大小?
是否仅通过分配新缓冲区,复制或移动所有元素并破坏先前的缓冲区来完成? 我认为这样效率低下。
答案 0 :(得分:1)
据我所知,C ++不支持像'realloc(void *,size_t)'这样的运算符
C ++确实有std::realloc
。但这不是(通常?)用于实现向量大小的调整。
然后如何在没有'realloc'函数的情况下调整std :: vector缓冲区的大小?
使用以下算法:
是否只是通过分配新缓冲区,复制或移动所有元素并破坏先前的缓冲区来完成?
是的。
我认为效率不高。
您为什么这么认为?正是realloc
所做的。当然,realloc
有时有时能够跳过复制,具体取决于内存布局,而矢量通常无法做到这一点。与手动malloc
化动态数组相比,这是vector的不幸缺点,但不一定有很大缺点。
有人提出了向标准分配器添加重新分配支持的建议,如果将其引入标准中,则将允许相同的优化:http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p0894r1.md
答案 1 :(得分:1)
std :: realloc 。
来源:https://en.cppreference.com/w/cpp/memory/c/realloc
因为重新分配可能涉及按字节复制(无论 无论是展开还是收缩),仅对象 在受保护的部分中,可以轻松地访问TriviallyCopyable类型 调用realloc之后的内存块。
一些非标准库定义了类型特征“ BitwiseMovable”或 “可重定位”,它描述的类型没有:
如果容器不知道对象是普通可复制的,则使用realloc扩展内存可能会导致数据损坏。
如果可以在容器上使用is_trivially_copiable,则可以,可以使用realloc。否则会导致不确定的行为。
否则,容器a)创建新内存,b)调用元素的复制或移动构造函数以将其移动到新内存c)释放旧内存。
答案 2 :(得分:0)
如果理论上为std::vector<bool>
,则内部不会使用等效于 realloc 的事实,但是要研究g ++的实现(gcc版本6.3.0 20170516 / Raspbian):
template<typename _Alloc>
void
vector<bool, _Alloc>::
_M_reallocate(size_type __n)
{
_Bit_pointer __q = this->_M_allocate(__n);
iterator __start(std::__addressof(*__q), 0);
this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), __start);
this->_M_deallocate();
this->_M_impl._M_start = __start;
this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
}
所以它基于新分配,然后复制然后取消分配
答案 3 :(得分:-1)
std :: vector 具有resize函数,可让您根据需要扩展或压缩数组。如果确实发生了重新分配,它将自动将元素复制/移动到新分配中。这就是迭代器可能变得无效的原因。