当我们删除一个指针时,会删除该指针所指向的对象。但是当STL容器中存放指针对象时却不会这样。
1 | // delete一个指针,会将该指针所指向的对象删除 |
可以在STL容器中存放对象,也可以用来存放对象的指针,在STL对象调用clear()或者erase()时,如果容器内存放的是对象实体,会被删除,但是如果容器内存储的是对象指针,会造成内存泄露(只删除了指针,而指针所指向的对象并不会被删除)。
考虑下面的代码:
1 | // for(type varName:object)是C++11的新特性——范围for语句。 |
运行结果:
很显然可以从结果中看到,虽然我们调用**strVector.clear()/erase()**删除了所有对象(指针),(预计)并期望释放它们的内存,但是可以看到指针指向的对象却依然存在,发生了内存泄露。
STL容器中存放的指针所指向的对象不会随着clear()/erase()清除对象而自动释放。
因为clear()/erase()清除每个元素时会自动调用对象的析构函数释放对象,但是当容器中存储的是对象指针时,使用clear()只会调用指针的析构函数,而指针的析构函数什么也不做。所以就会发生内存泄露。
这时候就需要我们自己手动管理内存了。
我们可以用delete手动删除strVector中每个指针所指向的对象:
1 | for(auto &index:strVector){ |
然后我们再输出strVectorCopy中指针指向的对象的值:
1 | for(auto &index:strVectorCopy){ |
运行结果:
可以看到,strVector中存储的指针指向的对象都已经被释放,这时我们访问的是悬垂指针指向的内存块,其结果是未定义的。
在使用STL时,应该注意以下两点:
- STL容器是以复制的方式工作的。当你把一个元素放入容器中,在容器中存放的实际上是这个元素的一个副本,副本所占的内存是STL容器自动分配的。当删除这个元素时,STL会自己调用该元素的析构函数来回收这些内存。
- 如果把指针放入容器中,删除元素的时候容器只负责回收指针本身所占的内存,但不会回收指针所指向的内容。