今天在程序里面有这么一段糟糕的代码:
运行结果如下:
while()
// cout << Memory1:
Type *a = new Type[MAX_N];
// cout << Memory2:
map<int, vector<Type> > m;
for()
m.insert(...);
// cout << Memory3:
delete[]a;
// cout << Memory4:
// use m
m.clear()
// cout << Memory5:
运行结果如下:
Memory1: Avali Pspace 1867726848
Memory2: Avali Pspace = 861089792
Memory3: Avali Pspace = 181284864
Memory4: Avali Pspace = 1187921920
Memory5: Avali Pspace = 1187921920
Memory1: Avali Pspace = 1187921920
bad_alloc
为什么第一次a可以申请成功,第二次就不行了呢,实际上第二次需要的空间与第一次的差不多,有时甚至还少一点?
大家可能都知道vector或者string采用clear()函数的时候只能清除元素,并不能清除内存,而要清除内存则可以用swap(),如下所示:
vector<int> v;
for(size_t i = 0; i < 100; ++i)
{
v.push_back(i);
}
cout << "size=" << v.size() << " capacity=" << v.capacity() << endl;
v.clear();
cout << "After clear(): " << v.size() << " " << v.capacity() << endl;
vector<int> (v).swap(v);
cout << "After swap(): " << v.size() << " " << v.capacity() << endl;
输出的结果是:
size=100 capacity=128
After clear(): 0 128
After swap(): 0 0
这里的capacity是指vector v的容量,也就是占用的内存,最开始之所以容量是128而不是100,是因为vector在push_back的时候容量是按照2的指数增长的。
当调用clear()函数之后,虽然size变成了0,但是其占据的内存并没有变,调用swap函数之后才能彻底的清除。
现在回来我们的问题,map是不是类似的原理?
我把上面m.clear()换成了map<int, vector<Type> > (m).swap(m),运行结果与上面类似,依然是在第二次出现bad_alloc。
有人说map里面的元素如果是vector的话,需要先将vector占据的内存彻底清除之后,再swap我们的map,于是乎,我将上面的m.clear()换成了如下代码:
map <int, vector<int> >::iterator it;
for (it = m.begin(); it != m.end(); ++it)
{
vector <int> ().swap(it->second);
}
map <int, vector< int> > ().swap(m);
你以为会出现振奋人心的结果吗?答案是否定的,结果还是跟上面一样,真心不知道m占据的那些内存去哪里了,Avali Pspace里始终没有。
真的不希望写到这里就结束,因为这个问题我还是没有能够解决,如果有好心人知道的话,麻烦能告知我一下,感激不尽。
但是,问题还是要解决的!
既然a和m需要比较大的空间,而且还在while循环里面,频繁的申请和释放确实不是一个好主意。另外while的每次循环中实际上a和m占用的内存差不多大,所以,可以将a和m需要的内存按照最大值在while循环的外面就给分配好(第一次是可以完成分配的),然后在while循环内部直接使用即可。