回答
请记住,如果您基于“顶部”或“任务管理器”测量内存使用情况,则“释放”的内存不一定实际上“设置为消失”。大多数现代堆管理员并没有将内存一直释放到操作系统级别,因为预期分配一次的内存将再次需要。只有当释放的数量达到一定的限制(连续的范围内,所以如果在释放的记忆海中存在仍然使用的记忆的小“岛屿”,它不能作为一个块被释放,并且很可能留在你的应用程序“永远”)。
对此,你无能为力,只能忍受它。如果您事先知道需要多少内存,请使用reserve()
来保留它。如果你不这样做,让它自己成长。内存被释放,它只是没有作为“自由内存”回馈给实际操作系统,它位于应用程序的堆中。如果整个系统的内存不足,那么未使用的内存将被换出,其他更有用的内容将被加载到内存中,因此它不会被“占用并且永远不能用于其他任何事情” 。 (当然,如果你有很多使用内存的岛屿不时被访问,那么很可能内存不能被重用)。
我不允许由于较少的信誉发表评论,但你可能会有所帮助:
c++ Vector, what happens whenever it expands/reallocate on stack?
这个想法是,你通过写出很好的答案和/或问题来获得足够的声誉,而不是将评论添加为答案。 – juanchopanza
@juanchopanza我完全同意!但是那样我想贡献,但实际上不允许;这听起来不够好!现在我有权发表评论,我也会遵循。应该这样,如果某人在任何合作伙伴网站上拥有最低限度的声誉,应该允许他在所有其他网站上执行该操作。 – CinCout
未能释放内存,它不再使用将是一个很明显的错误在执行的std::vector
。当然,错误的确发生了,所以你几乎不可能找到这样一个实现的问题,但是你通常会认为vector
经过了相当好的测试,所以找到这样的东西似乎是不太可能的(如果你这样做的话,它可能会只是在相对模糊的情况下发生的事情)。
当然,vector
使用Allocator
参数(默认为std::allocator<T>
)来执行实际分配和释放内存(等等)。因此,分配器类中的错误可能导致内存不能按预期方式释放。假设你使用std::allocator<T>
,我会很惊讶地看到这种情况发生,但是如果(例如)你使用别人的分配器类,问题可能会更有可能(分配器类的接口不是立即显而易见的,关于它的良好文档并不特别常见)。
在我看到的大多数(最近)实现中,vector
在空间不足时扩展了1.5倍。如果该因子小于中间值(〜1.6),并且先前的分配彼此连续,则它们(最终)将合计为可以满足稍后要求的块。如果因素大于中庸,他们永远不会。
如果std :: allocator使用与malloc()类似的OS接口,那么在每次删除(或免费)时,它并不总是将内存返回给操作系统。如果它足够大以处理稍后的分配,它将重用一个“不确定”的内存块。 – rcgldr
例如,这是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;
}
}
}
所以,你可以看到,载体使用分配器的deallocate
方法来删除旧的存储。如果这是默认的std :: allocator,则它在内部使用new
和delete
运算符。该运营商通常会拨打malloc
/free
方法。一些malloc实现有工具来分析堆和检测内存错误,也有一些选项可以禁用内部区域的内存缓存,所以当free
被调用时,你可以使它返回内存到操作系统。见tcmalloc和jemalloc。
- 1. 目标C重新分配变量
- 2. C++向量中动态分配向量?
- 3. C++向量分配问题
- 4. 向量C++内存分配
- 5. 未分配C++向量值
- 6. 重新分配变量值
- 7. 内存重新分配使用的std ::矢量重新分配
- 8. C#重新分配类
- 9. 数组重新分配C++
- 10. C++:自动向量重新分配调用复制构造函数?为什么?
- 11. 动态内存重新分配在自定义向量类
- 12. 循环重新分配向量元素matlab
- 13. map <string,vector <string>>向量值的重新分配
- 14. 转换分配/重新分配从C++多维数组到C
- 15. 如何分配给2d向量C++
- 16. 向量.reserve()和分配效率(C++)
- 17. 为MPI分配一个C++向量对
- 18. C++指针分配(指向矢量)
- 19. 重新分配
- 20. STL向量分配
- 21. 重新分配指向多维数组的指针C
- 22. 强迫变量重新分配(Prolog)
- 23. 重新分配变量不起作用
- 24. 重新分配POST输出变量
- 25. Gradle:doFirst中的变量重新分配
- 26. 重新分配变量列表
- 27. 无法重新分配局部变量
- 28. 变量为空直到重新分配
- 29. 不能重新分配$这个变量
- 30. PHP类别变量重新分配
std :: vector不会留下旧的未使用的内存作为内存泄漏,如果这是你要求的。然而,这适用于C++以及C:http://stackoverflow.com/questions/1556014/memory-usage-isnt-decreasing-when-using-free/1556024#1556024 –
我不认为标准保证任何事情,但是,一般来说,是的,当你超过当前容量时,向量将分配一个更大,连续的内存块并释放旧的块。 – Brian
感谢您的输入Brian Bi和Thomas Padron-McCarthy,我在向量中存储了12个表格,它占用了83.8 MB RAM,但是当我使用vector.reserve()时,它花费了37.8MB RAM,这接近实际大小。一行vector.reserve(1000000)使这种差异,这就是为什么我想知道这一点。 –