我在向Vector中加载数据时正在进行内存优化。我想知道Vector重新分配时Vector使用的内存会发生什么。我的意思是它是否被Vector释放了?
提前th。不前。答案 0 :(得分:2)
例如,这是gcc 4.8.2中的向量调整大小实现:
void resize(size_type __new_size)
{
if (__new_size > size())
_M_default_append(__new_size - size());
else if (__new_size < size())
_M_erase_at_end(this->_M_impl._M_start + __new_size);
}
因此,如果新大小大于当前矢量大小,则调用_M_default_append
:
template<typename _Tp, typename _Alloc>
void vector<_Tp, _Alloc>::_M_default_append(size_type __n)
{
if (__n != 0)
{
if (size_type(this->_M_impl._M_end_of_storage
- this->_M_impl._M_finish) >= __n)
{
std::__uninitialized_default_n_a(this->_M_impl._M_finish,
__n, _M_get_Tp_allocator());
this->_M_impl._M_finish += __n;
}
else // if new size is larger, execution flow goes here
{
//get size of a new memory block allocated for internal storage
const size_type __len =
_M_check_len(__n, "vector::_M_default_append");
const size_type __old_size = this->size();
//allocate new memory block
pointer __new_start(this->_M_allocate(__len));
pointer __new_finish(__new_start);
__try
{
//move existing elements to a new memory if stored objects are movable
//or just copy them
__new_finish
= std::__uninitialized_move_if_noexcept_a
(this->_M_impl._M_start, this->_M_impl._M_finish,
__new_start, _M_get_Tp_allocator());
//create new elements at the end of the storage
std::__uninitialized_default_n_a(__new_finish, __n,
_M_get_Tp_allocator());
__new_finish += __n;
}
__catch(...)
{
// if exception was thrown while coping, destroy elements in new storage
// and throw exception again
std::_Destroy(__new_start, __new_finish,
_M_get_Tp_allocator());
// deallocate new memory
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
// call destructors of the elements in the old storage
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
// deallocate memory used for the old storage
// _M_deallocate here checks if _M_start is not null and
// calls allocator's deallocate method
_M_deallocate(this->_M_impl._M_start,
this->_M_impl._M_end_of_storage
- this->_M_impl._M_start);
// set new storage to this vector object
this->_M_impl._M_start = __new_start;
this->_M_impl._M_finish = __new_finish;
this->_M_impl._M_end_of_storage = __new_start + __len;
}
}
}
因此,正如您所看到的,vector使用allocator的deallocate
方法来删除旧存储。如果这是默认的std :: allocator,它会在内部使用new
和delete
运算符。此运算符通常调用malloc
/ free
方法。一些malloc实现具有分析堆和检测内存错误的工具,还有一些可以选择在内部竞技场中禁用内存缓存,因此您可以在调用free
时将内存返回到OS。请参阅tcmalloc和jemalloc。
答案 1 :(得分:1)
由于声誉较低,我不允许发表评论,但您可能会觉得这很有用:
c++ Vector, what happens whenever it expands/reallocate on stack?
答案 2 :(得分:1)
在std::vector
的实现中,无法释放它不再使用的内存将是一个相当明显的错误。当然,错误确实发生了,所以你几乎不可能找到这样的实现问题,但你通常希望vector
得到相当好的测试,所以找到这样的东西似乎不太可能(如果你这样做,那可能只是在相对模糊的情况下发生的事情。)
当然,vector
使用Allocator
参数(默认为std::allocator<T>
)来进行实际分配和释放内存(以及其他内容)。因此,分配器类中的错误可能导致内存未按预期释放。假设你使用std::allocator<T>
,我会惊讶地看到这种情况发生,但是如果(例如)你正在使用其他人的分配器类,问题可能会更加可能(分配器类的接口是很明显,并且关于它的良好文档并不是特别常见。)
对于它的价值,在我看到的大多数(最近的)实现中,vector
在空间不足时扩展了1.5倍。如果因子小于黄金均值(~1.6)并且先前的分配彼此相邻,则它们(最终)将加起来以满足后来的要求。如果因子大于黄金均值,他们永远不会。
答案 3 :(得分:1)
请记住,如果您根据“top”或“任务管理器”测量内存使用情况,则“释放”的内存实际上并不一定“已经消失”。大多数现代堆管理器不会将内存一直释放到操作系统级别,因为期望再次需要分配一次的内存。只有一旦释放的量达到一定的限度(连续范围,所以如果在释放的记忆海洋中仍然使用的记忆的小“岛”,它不能被释放为一个块,并且很可能会留在你的申请“永远”)。
对此你无能为力,只是忍受它。如果您事先知道需要多少内存,请使用reserve()
进行保留。如果你不这样做,就让它自己成长。内存被释放,它只是没有作为“空闲内存”返回到实际操作系统,它位于应用程序的堆中。如果整个系统中的内存不足,那么未使用的内存将被换出,其他更有用的内容将被加载到内存中,因此它不会被“占用,永远不能用于其他任何东西” 。 (当然,如果你有很少的已使用内存孤岛,可以不时被访问,那么内存可能无法重用)。