[英]std::vector memory management
据我所知, std::vector
为它将包含的数据保留了一些内存,如果该内存已满,它将把所有数据复制到新的更大的内存块中。
例如,如果向量包含2个元素,则内存如下所示:
DD--XX----- D for vector's data, - for empty, X for other data
如果我添加两个元素,它将变成这样:
DDDDXX-----
但是如果我尝试添加另一个元素,向量将复制所有元素并释放以前的内存:
----XXDDDDD
我对吗 ??
现在,我不希望向量将成员复制到另一个内存块,因此我想知道他何时执行此操作。 可能吗 ? 例如,使用插入函数在发生这种情况时会引发异常
是的,您已经正确理解了std::vector
的行为。
您可以看到std::capacity
它给您向量的容量大小,意思是-在下一次重新分配之前,向量可以容纳多少元素。 你可以做类似的事情
std::vector< type >::size_type remaining_places = v.capacity() - v.size();
您不能完全防止这种情况,但是可以随时使用std::vector::reserve
更改向量的容量。
std :: vector的实际规范类似于
template < class T, class Alloc = allocator<T> > class vector;
其中, Alloc
是为了分配原始内存而委托给的对象的类型。
如果要拦截向量执行的调整大小操作,请提供适当定制的分配器。 量身定制的分配器(一个类,可能是模板类)将需要允许进行保留或设置大小的第一个操作,但在随后的调整大小尝试时将引发异常。 查找模板化的std::allocator
(在C ++中为std::allocator_traits
),以获取定制的分配器必须支持的接口规范。
我对吗 ??
均田。
您的图表使向量看起来像重新分配,否则将导致向量运行到其他分配的内存中。 这不是真的。 当向量用完分配的内存时, 它们会重新分配。 可能是这个
DD--------
DDD-------
------DDDD
即使没有任何X
这里的关键是向量执行的预分配。 假设您的向量的容量为4:
std::vector<int> v;
v.reserve(4);
v.push_back(999);
v.push_back(998);
v.push_back(997);
v.push_back(996);
这可能导致:
-------XX---------
PPPP---XX--------- set capacity
DPPP---XX--------- add element
DDPP---XX--------- add element
DDDP---XX--------- add element
DDDD---XX--------- add element
DDDD---XX--PPPPPPP increase capacity; requires new allocation...
DDDD---XX--DDDDPPP ... and copying of data ...
-------XX--DDDDPPP ... and de-allocation of the original memory
依此类推。
现在,我不希望向量将成员复制到另一个内存块,因此我想知道他何时执行此操作。 可能吗 ? 例如,使用插入函数在发生这种情况时会引发异常
并非如此,但是您可以将myVector.size()
与myVector.capacity()
进行比较,然后自己引发一个异常,而不是在两者相等时push
_back
。 这将防止向量本身通过重新分配和复制来处理这种情况。
听起来好像您希望向量在原地增长,然后在过程内存空间不足时抛出。 但是,据我所知,尚无操作系统级别的支持,当然C ++也无法访问。 (请注意,即使重新realloc
也可能会移动数据。)您可以发明一种新型的计算机来执行此操作。 从理论上讲,编写一个池分配器可以使您获得这一点,但是为什么呢? 就我所知,这是一件繁重的工作,而且语义令人惊讶-基本上根本没有任何好处。
指定std::vector
必须将元素存储在连续内存中。 这意味着,如果附加的值比连续可用的更多,它将在其他位置分配一个较大的连续块,并将这些值从旧的内存块移动到新的块。 这是正确的行为 ,您对此无能为力。
为了明确回答您的问题,向量将在
vector.size() == vector.capacity()
在此之后,单个push_back
或emplace_back
(等)将需要在其他位置进行其他分配,并且您会注意到.capacity()
的值将增加。
std :: vector将管理至少足够的内存以在其中容纳对象。
如果添加另一个导致空间用完的对象,它将自动增长-这是设计使然,无法防止,预测或检测到。
如果您的对象可移动,它们将被std::move
新内存中,而不是被复制。
向量中的所有对象都是连续的-永远不会有任何间隙(除了对齐要求所要求的填充)。
如果从中间删除一些项目,则末尾的项目将向下移动,以便矢量仍包含连续的项目。
如果要防止向量增长到一定大小,则必须对此进行编码(将向量包装在另一个类中?)
您可以使用std::vector::reserve()
在向量中保留空间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.