以前用vector,想释放时就用clear()函数清空,以为这样vector变量的内存就释放了。其实不是,详细解释看http://www.cnblogs.com/summerRQ/articles/2407974.html,临时对象的作用域就是其该语句,所以被析构的时候会释放内存。
主要是vector有自己的内存管理,为了保证插入时能很顺利,当现有的元素数达到其预分配的容量(capacity)时,它会另外申请两倍于当前容量的空间,前半部分copy存已有数据,后半部分用于未来的插入。vector的clear只是将其元素数量变为0,但容量不变,且空间不释放。
vector<int> nums;
nums.push_back(1);
nums.push_back(1);
nums.push_back(2);
nums.push_back(2);
vector<int>().swap(nums); //或者nums.swap(vector<int> ())
之后为了测试swap是否真的能释放内存,我写了下面代码,并在linux上用top -p [pid] 命令查看了程序占用内存(VIRT: KB):
int main()
{
char ch; //内存:7096
cout<<1<<"---"<<endl;
cin>>ch;
{
vector<string> ve;
cout<<endl<<2<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//内存:7096
cin>>ch;
for(int i=0;i<10000000;++i)
{
ve.push_back("dakjsdflsa");
}
cout<<endl<<3<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;// 10000000:16777216 内存:592M
cin>>ch;
ve.clear();
cout<<endl<<4<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//0:16777216 内存:<span style="font-family: Arial, Helvetica, sans-serif;">592M</span>
cin>>ch;
vector<string>().swap(ve);
cout<<endl<<5<<"---"<<ve.size()<<"::"<<ve.capacity()<<endl;//0:0 内存:464M
cin>>ch;
}
//内存:464m
cout<<endl<<6<<"---"; cin>>ch;
{
vector<string> ve;
cout<<endl<<2<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//内存:464m
cin>>ch;
for(int i=0;i<10000000;++i)
{
ve.push_back("dakjsdflsa");
}
cout<<endl<<3<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//10000000:16777216 内存:592m
cin>>ch;
ve.clear();
cout<<endl<<4<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//0:16777216 内存:592m
cin>>ch;
vector<string>().swap(ve);
cout<<endl<<5<<"---"<<ve.size()<<"::"<<ve.capacity()<<endl;//0:0 内存:464m
cin>>ch;
}
return 0;
}
可以看到:当想容器push后,内存急剧上升,用clear后内存不变,用swap后内存释放一部分(128m),但还是剩余464m大小的内存,一个程序中的第二次push的结果和第一次差不多,说明vector在第一次push、释放后,第二次的push是在原来的内存上做的,并没有重新申请类似128m大小的内存,应该是vector的缓存复用。
为解释swap后为什么还剩余464m这么大的内存,我将string改成了int:
{
vector<int> ve;
cout<<endl<<2<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//内存:7096
cin>>ch;
for(int i=0;i<10000000;++i)
{
ve.push_back(i);
}
cout<<endl<<3<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;// 10000000:16777216 内存:72768
cin>>ch;
ve.clear();
cout<<endl<<4<<"---"<<ve.size()<<":"<<ve.capacity()<<endl;//0:16777216 内存:<span style="font-family: Arial, Helvetica, sans-serif;">72768</span>
cin>>ch;
vector<int>().swap(ve);
cout<<endl<<5<<"---"<<ve.size()<<"::"<<ve.capacity()<<endl;//0:0 内存:7228
cin>>ch;
}
此次用swap释放vector后,内存降到了7228,和最开始时的7096相差不多,下降的65670KB的空间也大概是10000000个int数(实际vector申请了16777216个int空间)的内存大小。
int的程序可以说明,swap后,vector的内存确实是释放了,起码vector里的数据是释放了,但为什么string时还会保留那么多的内存呢? 不得其解!
后记:
学习了内存泄露工具valgrind后,我用valgrind检测上面的程序,发现不管是string还是int,不管是用没用swap释放内存,valgrind工具都显示程序没有内存泄露,这说明,当vector在程序退出时,程序会自动调用vector的析构将内存释放,只不过在程序运行的过程中,不用swap释放的vector内存会当成“缓存”继续占用程序内存。
另外,当vector的元素类型是指针时,在swap前需要delete或free容器的每一个元素。
还有,发现有个人有和我一样的困扰:http://www.dewen.org/q/7808/C%2B%2B%E4%B8%ADvector%E6%98%AF%E6%80%8E%E4%B9%88%E9%87%8A%E6%94%BE%E5%86%85%E5%AD%98