std::vector 中如何管理动态内存?

2023-12-08

std::vector如何实现对元素数量变化的管理:是使用realloc()函数,还是使用链表?

Thanks.


它使用作为第二个模板参数提供给它的分配器。那就这样吧。假设它在push_back中,让t是要推送的对象:

...
if(_size == _capacity) { // size is never greater than capacity
    // reallocate
    T * _begin1 = alloc.allocate(_capacity * 2, 0);
    size_type _capacity1 = _capacity * 2;

    // copy construct items (copy over from old location).
    for(size_type i=0; i<_size; i++)
        alloc.construct(_begin1 + i, *(_begin + i));
    alloc.construct(_begin1 + _size, t);

    // destruct old ones. dtors are not allowed to throw here. 
    // if they do, behavior is undefined (17.4.3.6/2)
    for(size_type i=0;i<_size; i++)
        alloc.destroy(_begin + i);
    alloc.deallocate(_begin, _capacity);

    // set new stuff, after everything worked out nicely
    _begin = _begin1;
    _capacity = _capacity1;
} else { // size less than capacity
    // tell the allocator to allocate an object at the right
    // memory place previously allocated
    alloc.construct(_begin + _size, t);
}
_size++; // now, we have one more item in us
...

类似的事情。分配器将关心分配内存。它将分配内存和在该内存中构造对象的步骤分开,因此它可以预分配内存,但还不能调用构造函数。在重新分配期间,向量必须注意复制构造函数抛出的异常,这使问题有些复杂。上面只是一些伪代码片段 - 不是真正的代码,并且可能包含许多错误。如果大小超过容量,它会要求分配器分配一个新的更大的内存块,如果没有,则它只是在先前分配的空间上构造。

其确切语义取决于分配器。如果是标准分配器,则构造即可

new ((void*)(_start + n)) T(t); // known as "placement new"

和分配allocate只会从中获取记忆::operator new. destroy会调用析构函数

(_start + n)->~T();

所有这些都在分配器后面抽象出来,向量只是使用它。堆栈或池分配器的工作方式可能完全不同。有关的一些要点vector那些很重要

  • 拨打电话后reserve(N),您最多可以将 N 个项目插入向量中,而无需承担重新分配的风险。在那之前,只要size() <= capacity(),对其元素的引用和迭代器仍然有效。
  • Vector的存储是连续的。您可以将 &v[0] 视为包含向量中当前拥有的尽可能多元素的缓冲区。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::vector 中如何管理动态内存? 的相关文章

随机推荐