std ::矢量内存管理

时间:2015-05-21 14:24:31

标签: c++ vector

据我所知,std::vector为它将包含的数据保留了一些内存,如果该内存已满,它会将所有数据复制到一个新的更大的内存块。

例如,如果向量包含2个元素,则内存如下:

DD--XX-----                  D for vector's data, - for empty, X for other data

如果我添加两个元素,它将变成这样:

DDDDXX-----

但如果我尝试添加另一个元素,则向量将复制所有元素并释放先前的内存:

----XXDDDDD

我是对的吗?

现在我不希望向量将成员复制到另一块内存中,所以我想知道他什么时候这样做。可能吗 ?使用插入函数,例如在发生这种情况时抛出异常

5 个答案:

答案 0 :(得分:2)

是的,您已正确了解std::vector的行为。

您可以观看std::capacity - 它会为您提供向量容量的大小,这意味着 - 在下次重新分配之前,向量可以保存的元素如何。你可以做点什么

std::vector< type >::size_type remaining_places = v.capacity() - v.size();

您无法完全阻止此操作,但您可以随时使用std::vector::reserve更改矢量容量。

答案 1 :(得分:2)

std :: vector的实际规范类似于

template < class T, class Alloc = allocator<T> > class vector;

其中Alloc是为了分配原始内存而委派给的对象的类型。

如果要拦截矢量执行的调整大小操作,请提供适当定制的分配器。您定制的分配器(一个类,可能是模板化的)将需要允许第一个保留或设置大小的操作,但在随后的大小调整尝试中抛出异常。查找模板std::allocator(以及在C ++``,std::allocator_traits中),了解您的定制分配器必须支持的接口规范。

答案 2 :(得分:1)

  

我是对的吗?

有点儿。

您的图表使得它看起来像向量重新分配,如果不这样做会导致它们运行到其他已分配的内存中。那不是真的。当媒体耗尽他们分配的内存时,向量会重新分配。可能是这个

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。这将阻止向量本身通过重新分配和复制来处理这种情况。

听起来你希望vector能够尽可能多地增长就地,然后在进程内存空间耗尽时抛出。但是,据我所知,没有操作系统级别的支持,当然也没有C ++可以访问的内容。 (请注意,即使realloc也可能会移动数据。)您可以创建一种新型计算机来执行此操作。从理论上讲,编写池分配器可以让你这样做,但为什么?这是一项非常多的工作和惊人的语义 - 据我所知 - 基本上没有任何好处。

答案 3 :(得分:0)

指定13:54:25.404 [DEBUG] [.io.transport.mqtt.MqttService:123 ] - Starting MQTT Service... 13:54:26.471 [INFO ] [.io.transport.mqtt.MqttService:108 ] - MQTT Service initialization completed. 13:54:26.480 [INFO ] [o.i.t.m.i.MqttBrokerConnection:114 ] - Starting MQTT broker connection 'eclipsemqttbroker' 13:54:26.537 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:294 ] - Creating new client for 'tcp://m2m.eclipse.org:1883' using id 'openHabEnOcean' and file store '/tmp/eclipsemqttbroker' 13:34:11.850 [DEBUG] [b.mqtt.internal.MqttItemConfig:71 ] - Loaded MQTT config for item 'MyRocker' : 0 subscribers, 2 publishers 13:34:11.904 [DEBUG] [m.internal.MqttEventBusBinding:61 ] - MQTT: Activating event bus binding. 存储连续内存中的元素。这意味着如果附加的值多于连续可用的值,它将在其他地方分配一个更大的连续块,并将值从旧的内存块移动到新块。这是正确的行为,您无能为力,或者应该对此采取任何行动。

要专门回答您的问题,

时矢量将“满”
std::vector

此后的单vector.size() == vector.capacity() push_back(等)需要在其他位置进行其他分配,您会注意到emplace_back的值会增加。

答案 4 :(得分:0)

std :: vector将管理至少足够的内存来保存其中的对象。

如果添加另一个导致空间不足的对象,它将自动增长 - 这是设计使然无法阻止,预测或检测到的。

如果您的对象具有移动感知功能,则它们将std::move放置在新内存中,而不是复制。

向量中的所有对象都是连续的 - 从不存在任何间隙(除了对齐要求所需的填充)。

如果您从中间删除了一些项目,那么末尾的项目会向下移动,以便向量仍包含连续的项目。

如果你想阻止向量增长超过一定的大小,你必须为它编码(将向量包装在另一个类中?)

您可以使用std::vector::reserve()

预先在矢量中预留空间