std::vector<T> vSum;
答案
1、当 T 为指针时,释放内存的代码如下:
for(auto &x:vSum)
{
delete x;
}
std::vector<T>().swap(vSum);
2、当 T 为原生类型(int、float、char)时,释放内存的代码如下:
std::vector<T>().swap(vSum);
3、当 T 为类对象时,释放内存的代码如下:
vSum.clear();
std::vector<T>().swap(vSum);
说明
大家可以看到,释放内存共用到了两个函数,分别是 clear() 和 swap() ,弄明白这两个函数的功能也就清楚了 vector 释放内存的原理了。
1、clear() 函数(stl_vector.h)
有此可知 clear 函数调用的是 erase 函数。
erase 函数的操作过程是将 last 到 finish 之间的元素移动到 first 元素的位置,然后删掉从 first + (finish - last) 为开始 finish 之间所有的元素。删除操作就是由 destory() 函数完成。下面看下 destory 函数的内容。 (stl_construct.h)
我们可以发现 __destroy 比 destroy 多了第3个参数 value_type(first) ,该函数的原型如下:(stl_iterator.h)
该函数的作用是返回 Iterator 的型别,即:数据类型。 好,在深入到 iterator_traits 看下其是如何知道 Iterator 的型别的。(stl_iterator.h)
上述代码中的 value_type 就是 vector 类中的
typedef T value_type;
也就是 value_type 函数返回的值就是 T *类型的值为 0 的地址。好,咱们进 __destory() 函数看下
这里面的关键就是代码
typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
它的作用是返回类型 T 是否含有析构函数!具体可以看其的实现,采用的是模板特化的方案。好了,如果类型 T ,有析构函数,则进入如下代码,
若是类型 T 没有析构函数,则执行如下代码
所以,经过上述代码的梳理,我们可以得到结论:clear() 函数实际上是尝试执行指定范围内每个要素的析构函数,如果 T 是原生的类型或者是指针,那么 clear() 就不会再做任何事情了。 所以该函数不会释放 vector 本身申请的内存!那负责释放内存的工作就落到了 std::vector<T>().swap(vSum); 头上了!
所以,只有 T 为对象时,执行 clear() 才有意义。当然了,为了节约大脑资源,无论 T 为什么类型,都可以把 clear() 函数加上。
2、swap() 函数。
swap() 函数原型
该函数的作用就是交换两个 vector 的 start、finish 和 end_of_storage 。 用在 std::vector<T>().swap(vSum); 上时,相当于 临时的 vector 对象的 3 个指针指向了 vSum 中的内存,vSum 的 3 个指针指向了临时对象中的内存(空的),由于该代码执行完之后,临时对象就销毁了,所以就间接完成了释放 vSum 所申请的内存的目的!
总结
总之一条原则,自己 new 的自己去 delete 释放;不是自己 new 的,就不该你去释放。
往 vector 里面插入元素是对象时,vector 会负责执行这些对象的析构函数,因为内存是自己申请的。但是如果存在里面是对象的指针时,因为对象指针指向的对象的内存是程序员自己申请的,所以 vector 不会管(不会执行对象的析构函数)!
上述是 STL 通理。
拓展
(SAW:Game Over!)