据我所知,std::vector
为它将包含的数据保留了一些内存,如果该内存已满,它会将所有数据复制到一个新的更大的内存块。
例如,如果向量包含2个元素,则内存如下:
DD--XX----- D for vector's data, - for empty, X for other data
如果我添加两个元素,它将变成这样:
DDDDXX-----
但如果我尝试添加另一个元素,则向量将复制所有元素并释放先前的内存:
----XXDDDDD
我是对的吗?
现在我不希望向量将成员复制到另一块内存中,所以我想知道他什么时候这样做。可能吗 ?使用插入函数,例如在发生这种情况时抛出异常
答案 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()