请教一个关于vector的问题

时间:2022-12-05 19:52:51
我在程序中clear一个很大的vector 它所占用的内存不能全部的释放, 再次向vector中插入大量数据,再次clear 它还是占用那么大的内存.

就是说一个大的vector始终占用了一定量的内存 clear或者和一个空vector交换后内存没有完全释放,而要到关闭程序后才释放? 
有什么方法可以释放掉vector中占用的全部内存呢?

71 个解决方案

#1


显式使用capacity,设置vector的容量

#2


关注

#3


vector为了防止大量分配连续内存的开销,
保持一块默认的尺寸的内存,clear只是清数据了
未清内存,因为vector的capacity容量未变化,系统维护一个的默认值

#4


再次clear 它还是占用那么大的内存.

=======================================
你确定是它占用的么??

#5


把它显式置为0则通知编译器不为这个vector预留内存(连续)
个人意见,高手多多指教

#6


试试 resize(0);如果不行只能析构vector对象了

#7


再次clear 它还是占用那么大的内存.
=================
这个倒不一定,举个例的说明,
假设编译器默认的capacity为10,当你插入11个元素的时候,编译器把capacity设置为20(一般的编译器都翻倍处理),这时你的vector占20个元素的内存,这时你clear,把数据清了,vector为空了,capacity又变成了默认值的10,即这时占10个元素的内存了

#8


一个简单的办法是重新声明一个VECTOR,把它赋给以前的VECTOR,这样就没什么问题了。不过这么做感觉不大好,如果可以显式指定CAPACITY那就指定把。
VECTOR的工作原理是系统预先分配一块CAPACITY大小的空间,当插入的数据超过这个空间的时候,这块空间会让某种方式扩展,但是你删除数据的时候,它却不会缩小。

#9


看effective STL item17

#10


你用的什么编译器?我在vs7.0里面看的是好用的。
--------------------------------------------
标准的解决方法如下
template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}

#11


delete

#12


to sirguan(123)
==============
高,实在是高

#13


有什么方法可以释放掉vector中占用的全部内存呢?
-------------------------------------------------------------------------------------
和一个空的vector进行swap是你能够得到的最好结果。
因为如果具体的实现要求"空的"vector也必须有数据的话,则你没有办法让vector“真正”为“空”的。

#14


因为如果具体的实现要求"空的"vector也必须有数据的话,则你没有办法让vector“真正”为“空”的。

改为:
因为如果具体的实现要求"空的"vector也必须保留一定的空间的话,则你没有办法让vector“真正”为“空”的。

不好意思^_^

#15


是的,一般拿那个vector和一个空的进行swap就可以释放一定的空间,是不是为空,就如楼上所说的不一定了

上面有人写了:标准的解决方法如下
template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}

#16


楼上的标准解决方法是不是也不一定为空??

#17


zengguowen1984(性格,就是艺术),看effective STL item17

#18


我想说的别人都说了

#19


大家都说了,我就接分好了

#20


重要的是搞清楚原因,正好模拟实现过,把学到的讲出来,大家分享下:

vector 是在内存中申请连续的内存空间,
当这块内存放满数据后,会在另外的地址申请一块比现有内存要大的,
然后把数据拷贝过去,再往后面加入新的数据;
原有内存被释放。
所以vector对象就会越来越肥,一发不可收拾

这个只和包含的库有关系,不关其它的什么事...

#21


你应该使用swap惯用手法.

vector<T>(a).swap(a);

a 为 你要压缩的vector<T>

#22


该回复被版主删除

#23


为什么似乎所有的人都认为vector的内存管理直接对应操作系统的内存管理?
一个vector删除了元素,内存就未必马上归还给操作系统吗?关键看系统和库的管理策略,完全可能程序仍然保留着那块内存,必要时给同一进程中的其它动态申请使用。
而且,在这个问题上,不同的操作系统平台上,不同的编译器中,策略不尽相同?
当然,大多数情况下会跟一次性申请/释放的数量有关系。

#24


没办法,他们都不看《STL源码剖析》

#25


偶也没看。:P
sorry,上面有一处问号就改为句号。

#26


还是看看吧。C++界里最优秀的代码了。

#27


嗯,一定。:)

#28


晨星 就是强啊。

#29


STL用的是底层的自己实现的一个内存管理框架:多半也是用伙伴算法的(至少SGI的是如此)。

大家都知道不会自动释放,所以问怎么释放而已,以为就你们看过?

#30


支持这种方式:vector<T>(v).swap(v);
只是这种方式缩减以后,此vector v的所有references,pointers和iterators全部失效。

#31


vector<X> vec;
...    //vec.capacity() is large, but contains few elements
vec.reserve(vec.size());     //now vec.capacity() == vec.size() == number of elements in vec

#32


ok,我承认上面是开玩笑的,我支持:
vector<T>(v).swap(v);

#33


偶承认偶没看过《STL源码剖析》,但关键问题是,在大多数情况下,这个问题不是STL的实现者自已能说得算的问题。

vector即使保证把底层占用的内存“释放”了,也并不意味着程序就立即归还给操作系统了,vector只是程序中某处的一个对象,它不用了不代表程序也不用了。

#34


从应用程序的级别,用swap也差不多了。
如果swap之后从任务管理器中观察到有效果,那当然最好不过;如果没有效果,那也只能认了。
再要往下追,不是没意义,但至少是超出C++程序设计的层面和角度了,我觉得。

#35


SGI的stl不存在类似gc的功能:

事实上,vector根本就不管内存,它只是负责向内存管理框架acquire/release内存,内存管理框架如果发现内存不够了,就malloc,但是当vector释放资源的时候(比如destruct), stl根本就不调用free以减少内存,因为内存分配在stl的底层:stl假定如果你需要更多的资源就代表你以后也可能需要这么多资源(你的list, hashmap也是用这些内存),所以就没必要不停地malloc/free。 如果是这个逻辑的话这可能是个trade-off

至于应用层面可以显示地告知内存管理框架说我现在不用了,你释放一些吧,也还算合理:
   vector<T> vworking;
   {
      vector<T> vupdating = vworking;
      // 这里vupdating申请的内存(拷贝)永远不会被释放
      // 这在vworking的内容很大时候会很糟糕
   }
  
所以stl可以有一个这样的tricky:shrink to fit,也就是上面的swap

其实我觉得stl应该有一个标准的方法来shrink to fit

同意stl是最优秀的代码之一,值得学习。

#36


"Michael Andersson" <a98mi...@ida.his.se> wrote in message 


news:3ECA8B4A.4020204@ida.his.se... 

> Does the STL specification say anything about whether or not 
> vector::clear will release allocated memory when called? Or is this only 
> performed when reserve is called with a value less than capacity? 


None of these will. 

The common idiom to clear a vector and release the memory it allocated 
is: 
  vector<TheItemType>().swap( theVectorToClear ); 


This creates an empty temporary vector and swaps its contents with 
those of the provided variable. The destructor of the temporary 
will then typically release memory previously associated with 
the variable. 


It is not formally guaranteed to work -- but in practice it does. 
(and because it has become a common C++ idiom, I do not think that 
 a library implementer would want to provide a different behavior). 


hth, 
-- 
 Ivan Vecerina, Dr. med.  <>  http://www.post1.com/~ivec 
 Soft Dev Manger, XiTact  <>  http://www.xitact.com 
 Brainbench MVP for C++   <>  http://www.brainbench.com

#37


这个问题我觉得应该是楼主自己的程序有问题,举例如下:


typedef struct tagTest
{
  int x;
  int y;
}tTest;

int main()
{
  vector< DWORD > vtTest;
  tTest *pt = NULL;
  for(int i = 0; i < 1000; i++)
  {
    pt = new tTest;
   vtTest.push_back((DWORD)pt);    
   }

   vtTest.clear();
}

vector 存放的是指针值,如果你只是简单的vtTest.clear(),而没有释放其分配的对象,内存是释放不了。

正确的释放如下:

vector< DWORD>::iterator it = vtTest.begin();

while(it != vtTest.end())
{
  pt = (tTest *)(*it);
  delete pt;
  it++;
}
vtTest.clear();

#38


vector保持一块默认的尺寸的内存

#39


mark

#40


在stl里面有个设备空间配置器,用它来销毁

#41


这个问题我一直没有注意到,mark

#42


一般的STL内存管理器allocator都是用内存池来管理内存的,所以某个容器申请内存或释放内存都只是影响到内存池的剩余内存量,而不是真的把内存归还给系统。这样做一是为了避免内存碎片,二是提高了内存申请和释放的效率——不用每次都在系统内存里寻找一番。
真的让容器把不用的内存归还给系统的话,楼主只能自己写一个allocator,并在容器的模板参数里使用它,而且STL的标准容器确实都留了这个接口。
不过楼主要意识到这样做给程序性能和系统内存带来的影响。

#43


clear和erase可以很好地减少了vector的大小(size),但没有减少它的容量(capactiy)
vector<T>(v).swap(v);
// 使用“交换技巧”来修整过剩容量
这种方式使vector的size == capactiy

STL中的内存分配一般采用内存池策略,如果单纯的通过任务管理察看应用程序的
使用量,发现当使用stl库的vector或者其他容器进行清空数据后,内存变化显著,反而
不能使用,因为这时STL库在内存上没有做优化。

上面有两本书《effective STL》,《深入剖析STL》值得一读


#44


忘记补充一下:
vector<T>(v).swap(v);
// 使用“交换技巧”来修整过剩容量
这种方式并不能保证这个技术会真的消除多余的空间。

#45


vector<T>(v).swap(v);

还是

vector<T>().swap(v); 

:)

#46


前者,
后者由于产生的临时对象是一个内容为空的vector<T>对象,
这样可以用于清除容器和减少它的容量到你的实现提供的最小值

#47


哇 好多回帖阿 感谢感谢 学习ing

这个是不是和编译器有关系呢
我用的是C++ buidler 
我是在程序中使用了swap,单步跟踪程序并查看任务管理器,执行过swap时内存没有动静,capacity()返回的值为0,但是占用的内存没有释放掉,只有在函数结束,也就是在vector的生命结束时 才释放了一小部分 还有一大部分vector占用的没有释放,再次在别的按钮事件中用同样的代码,这部分没有释放的内存一直就是被vector使用了,不回归了,而且vector越大占用的越大。 哈哈~~
刚才用vc7.1试了一下 结果完全不同, 执行到clear()或者swap时候内存全释放了,capacity()返回的值也为0了,连clear()方法也一样,也修改了capacity的值;
我晕了~~

#48


vector<T>(v).swap(v);

会所有对象复制一遍,然后交换,然后释放。。。
为什么这么做?

#49


resize不行吗?

#50


to:Wolf0403(废人)(Leading to nowhere...)
目的就是通过“交换技巧”来修整过剩容量

使用这种方法的前提是vector从前存储了大量数据,比如10000000,经过
各种处理后,现在只有100条,那么向清空原来数据所占有的空间,就可以
通过这种交换技术

具体参考effective STL 中的item17

#1


显式使用capacity,设置vector的容量

#2


关注

#3


vector为了防止大量分配连续内存的开销,
保持一块默认的尺寸的内存,clear只是清数据了
未清内存,因为vector的capacity容量未变化,系统维护一个的默认值

#4


再次clear 它还是占用那么大的内存.

=======================================
你确定是它占用的么??

#5


把它显式置为0则通知编译器不为这个vector预留内存(连续)
个人意见,高手多多指教

#6


试试 resize(0);如果不行只能析构vector对象了

#7


再次clear 它还是占用那么大的内存.
=================
这个倒不一定,举个例的说明,
假设编译器默认的capacity为10,当你插入11个元素的时候,编译器把capacity设置为20(一般的编译器都翻倍处理),这时你的vector占20个元素的内存,这时你clear,把数据清了,vector为空了,capacity又变成了默认值的10,即这时占10个元素的内存了

#8


一个简单的办法是重新声明一个VECTOR,把它赋给以前的VECTOR,这样就没什么问题了。不过这么做感觉不大好,如果可以显式指定CAPACITY那就指定把。
VECTOR的工作原理是系统预先分配一块CAPACITY大小的空间,当插入的数据超过这个空间的时候,这块空间会让某种方式扩展,但是你删除数据的时候,它却不会缩小。

#9


看effective STL item17

#10


你用的什么编译器?我在vs7.0里面看的是好用的。
--------------------------------------------
标准的解决方法如下
template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}

#11


delete

#12


to sirguan(123)
==============
高,实在是高

#13


有什么方法可以释放掉vector中占用的全部内存呢?
-------------------------------------------------------------------------------------
和一个空的vector进行swap是你能够得到的最好结果。
因为如果具体的实现要求"空的"vector也必须有数据的话,则你没有办法让vector“真正”为“空”的。

#14


因为如果具体的实现要求"空的"vector也必须有数据的话,则你没有办法让vector“真正”为“空”的。

改为:
因为如果具体的实现要求"空的"vector也必须保留一定的空间的话,则你没有办法让vector“真正”为“空”的。

不好意思^_^

#15


是的,一般拿那个vector和一个空的进行swap就可以释放一定的空间,是不是为空,就如楼上所说的不一定了

上面有人写了:标准的解决方法如下
template < class T >
void ClearVector( vector< T >& vt )
{
vector< T > vtTemp;
veTemp.swap( vt );
}

#16


楼上的标准解决方法是不是也不一定为空??

#17


zengguowen1984(性格,就是艺术),看effective STL item17

#18


我想说的别人都说了

#19


大家都说了,我就接分好了

#20


重要的是搞清楚原因,正好模拟实现过,把学到的讲出来,大家分享下:

vector 是在内存中申请连续的内存空间,
当这块内存放满数据后,会在另外的地址申请一块比现有内存要大的,
然后把数据拷贝过去,再往后面加入新的数据;
原有内存被释放。
所以vector对象就会越来越肥,一发不可收拾

这个只和包含的库有关系,不关其它的什么事...

#21


你应该使用swap惯用手法.

vector<T>(a).swap(a);

a 为 你要压缩的vector<T>

#22


该回复被版主删除

#23


为什么似乎所有的人都认为vector的内存管理直接对应操作系统的内存管理?
一个vector删除了元素,内存就未必马上归还给操作系统吗?关键看系统和库的管理策略,完全可能程序仍然保留着那块内存,必要时给同一进程中的其它动态申请使用。
而且,在这个问题上,不同的操作系统平台上,不同的编译器中,策略不尽相同?
当然,大多数情况下会跟一次性申请/释放的数量有关系。

#24


没办法,他们都不看《STL源码剖析》

#25


偶也没看。:P
sorry,上面有一处问号就改为句号。

#26


还是看看吧。C++界里最优秀的代码了。

#27


嗯,一定。:)

#28


晨星 就是强啊。

#29


STL用的是底层的自己实现的一个内存管理框架:多半也是用伙伴算法的(至少SGI的是如此)。

大家都知道不会自动释放,所以问怎么释放而已,以为就你们看过?

#30


支持这种方式:vector<T>(v).swap(v);
只是这种方式缩减以后,此vector v的所有references,pointers和iterators全部失效。

#31


vector<X> vec;
...    //vec.capacity() is large, but contains few elements
vec.reserve(vec.size());     //now vec.capacity() == vec.size() == number of elements in vec

#32


ok,我承认上面是开玩笑的,我支持:
vector<T>(v).swap(v);

#33


偶承认偶没看过《STL源码剖析》,但关键问题是,在大多数情况下,这个问题不是STL的实现者自已能说得算的问题。

vector即使保证把底层占用的内存“释放”了,也并不意味着程序就立即归还给操作系统了,vector只是程序中某处的一个对象,它不用了不代表程序也不用了。

#34


从应用程序的级别,用swap也差不多了。
如果swap之后从任务管理器中观察到有效果,那当然最好不过;如果没有效果,那也只能认了。
再要往下追,不是没意义,但至少是超出C++程序设计的层面和角度了,我觉得。

#35


SGI的stl不存在类似gc的功能:

事实上,vector根本就不管内存,它只是负责向内存管理框架acquire/release内存,内存管理框架如果发现内存不够了,就malloc,但是当vector释放资源的时候(比如destruct), stl根本就不调用free以减少内存,因为内存分配在stl的底层:stl假定如果你需要更多的资源就代表你以后也可能需要这么多资源(你的list, hashmap也是用这些内存),所以就没必要不停地malloc/free。 如果是这个逻辑的话这可能是个trade-off

至于应用层面可以显示地告知内存管理框架说我现在不用了,你释放一些吧,也还算合理:
   vector<T> vworking;
   {
      vector<T> vupdating = vworking;
      // 这里vupdating申请的内存(拷贝)永远不会被释放
      // 这在vworking的内容很大时候会很糟糕
   }
  
所以stl可以有一个这样的tricky:shrink to fit,也就是上面的swap

其实我觉得stl应该有一个标准的方法来shrink to fit

同意stl是最优秀的代码之一,值得学习。

#36


"Michael Andersson" <a98mi...@ida.his.se> wrote in message 


news:3ECA8B4A.4020204@ida.his.se... 

> Does the STL specification say anything about whether or not 
> vector::clear will release allocated memory when called? Or is this only 
> performed when reserve is called with a value less than capacity? 


None of these will. 

The common idiom to clear a vector and release the memory it allocated 
is: 
  vector<TheItemType>().swap( theVectorToClear ); 


This creates an empty temporary vector and swaps its contents with 
those of the provided variable. The destructor of the temporary 
will then typically release memory previously associated with 
the variable. 


It is not formally guaranteed to work -- but in practice it does. 
(and because it has become a common C++ idiom, I do not think that 
 a library implementer would want to provide a different behavior). 


hth, 
-- 
 Ivan Vecerina, Dr. med.  <>  http://www.post1.com/~ivec 
 Soft Dev Manger, XiTact  <>  http://www.xitact.com 
 Brainbench MVP for C++   <>  http://www.brainbench.com

#37


这个问题我觉得应该是楼主自己的程序有问题,举例如下:


typedef struct tagTest
{
  int x;
  int y;
}tTest;

int main()
{
  vector< DWORD > vtTest;
  tTest *pt = NULL;
  for(int i = 0; i < 1000; i++)
  {
    pt = new tTest;
   vtTest.push_back((DWORD)pt);    
   }

   vtTest.clear();
}

vector 存放的是指针值,如果你只是简单的vtTest.clear(),而没有释放其分配的对象,内存是释放不了。

正确的释放如下:

vector< DWORD>::iterator it = vtTest.begin();

while(it != vtTest.end())
{
  pt = (tTest *)(*it);
  delete pt;
  it++;
}
vtTest.clear();

#38


vector保持一块默认的尺寸的内存

#39


mark

#40


在stl里面有个设备空间配置器,用它来销毁

#41


这个问题我一直没有注意到,mark

#42


一般的STL内存管理器allocator都是用内存池来管理内存的,所以某个容器申请内存或释放内存都只是影响到内存池的剩余内存量,而不是真的把内存归还给系统。这样做一是为了避免内存碎片,二是提高了内存申请和释放的效率——不用每次都在系统内存里寻找一番。
真的让容器把不用的内存归还给系统的话,楼主只能自己写一个allocator,并在容器的模板参数里使用它,而且STL的标准容器确实都留了这个接口。
不过楼主要意识到这样做给程序性能和系统内存带来的影响。

#43


clear和erase可以很好地减少了vector的大小(size),但没有减少它的容量(capactiy)
vector<T>(v).swap(v);
// 使用“交换技巧”来修整过剩容量
这种方式使vector的size == capactiy

STL中的内存分配一般采用内存池策略,如果单纯的通过任务管理察看应用程序的
使用量,发现当使用stl库的vector或者其他容器进行清空数据后,内存变化显著,反而
不能使用,因为这时STL库在内存上没有做优化。

上面有两本书《effective STL》,《深入剖析STL》值得一读


#44


忘记补充一下:
vector<T>(v).swap(v);
// 使用“交换技巧”来修整过剩容量
这种方式并不能保证这个技术会真的消除多余的空间。

#45


vector<T>(v).swap(v);

还是

vector<T>().swap(v); 

:)

#46


前者,
后者由于产生的临时对象是一个内容为空的vector<T>对象,
这样可以用于清除容器和减少它的容量到你的实现提供的最小值

#47


哇 好多回帖阿 感谢感谢 学习ing

这个是不是和编译器有关系呢
我用的是C++ buidler 
我是在程序中使用了swap,单步跟踪程序并查看任务管理器,执行过swap时内存没有动静,capacity()返回的值为0,但是占用的内存没有释放掉,只有在函数结束,也就是在vector的生命结束时 才释放了一小部分 还有一大部分vector占用的没有释放,再次在别的按钮事件中用同样的代码,这部分没有释放的内存一直就是被vector使用了,不回归了,而且vector越大占用的越大。 哈哈~~
刚才用vc7.1试了一下 结果完全不同, 执行到clear()或者swap时候内存全释放了,capacity()返回的值也为0了,连clear()方法也一样,也修改了capacity的值;
我晕了~~

#48


vector<T>(v).swap(v);

会所有对象复制一遍,然后交换,然后释放。。。
为什么这么做?

#49


resize不行吗?

#50


to:Wolf0403(废人)(Leading to nowhere...)
目的就是通过“交换技巧”来修整过剩容量

使用这种方法的前提是vector从前存储了大量数据,比如10000000,经过
各种处理后,现在只有100条,那么向清空原来数据所占有的空间,就可以
通过这种交换技术

具体参考effective STL 中的item17