1.vector元素的清除

看代码。在vector中添加若干元素,然后clear()

 #include<iostream>
#include<list>
#include<vector>
#include<iterator>
#include<string>
using std::vector;
using std::list;
using std::iterator;
using std::string;
using std::cout;
using std::endl; int main()
{
vector<string> vecStr;
string pStr1 = "Robb";
vecStr.push_back(pStr1);
string pStr2 = "Bran";
vecStr.push_back(pStr2);
string pStr3 = "Snow";
vecStr.push_back(pStr3);
string pStr4 = "Sansa";
vecStr.push_back(pStr4);
string pStr5 = "Arya";
vecStr.push_back(pStr5); /*打印*/
for(auto unit:vecStr)
{
cout<<"-----"<<unit<<"-----"<<endl;
}
/*释放前vector的容量*/
cout<<"释放前vector的容量"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl; /*释放*/
vecStr.clear();
cout<<endl<<"clear后vector的容量"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
system("pause");
return ;
}

输出结果如图:

size是变小了,但是capacity并没有变小。

我们加一下代码

     /*swap*/
vector<string>().swap(vecStr);
cout<<endl<<"swap后vector的容量"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<end

使用swap之后,就清空了capacity。

这是为什么呢?

vector由于是一个不定长存储的数据结构,每一次分配的大小都是比面前输入的数据个数略大一点(实际上也并不准确,参看2)code中注释,是介于2^n与2^(n+1)之间),所以每一次push_back()且发现当被分配的存储空间已装满数据时,都是将包含现有数据的vector进行拷贝,进入一个更大一点的vector,而原有的vector就会被自然销毁,我们用.swap()释放内存的原理其实是相似的,即手动进行了一次人工拷贝的操作。(https://blog.csdn.net/a272846945/article/details/51182144 )

由于vector的空间是阶梯递增式管理的,而且基本只增不减,也就是说,虽然调用remove、erase或者clear等方法(他们会调用所存元素对象的析构函数),确实会释放掉一些内存,但是,容器之前分配的空间仍不会被回收,大小不变,仍旧不能被其他程序使用,这是由STL的内存管理机制决定的,目的是为了提高效率。 (https://www.cnblogs.com/EE-NovRain/archive/2012/06/12/2546500.html)

下面有一个调用函数的例子,感觉还是有很多东西

①内存增长方式,指数增长。2^n。数量增大到capacity的时候,整体拷贝,然后析构之前的内存。

②push_back,调用复制构造函数。

 class CUnit
{
private:
/* data */
string m_name;
public: CUnit(string name)
{
m_name = name;
//cout<<this<<",create"<<endl;
}
~CUnit()
{
//delete member
cout<<this<<",destroy"<<endl;
}
CUnit(const CUnit & c)
{
//cout<<&c<<",param"<<endl;
//cout<<this<<",copy"<<endl;
}
string& getName(){return m_name;}
}; int main()
{
vector<CUnit> vecStr;
CUnit cUnit1 = CUnit("Robb");
vecStr.push_back(cUnit1); //此处调用复制构造函数 cout<<"push one"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl; CUnit cUnit2 = CUnit("Bran");//size不够,多次复制构造
vecStr.push_back(cUnit2); cout<<"push two"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
CUnit cUnit3 = CUnit("Snow");//size不够,多次复制构造
vecStr.push_back(cUnit3);
CUnit cUnit4 = CUnit("Arya");//size不够,多次复制构造
vecStr.push_back(cUnit4);
CUnit cUnit5 = CUnit("Sansa");//size不够,多次复制构造
vecStr.push_back(cUnit5);
cout<<"push five"<<endl;
cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
cout<<endl; /*打印*/
for(auto unit:vecStr)
{
cout<<"-----"<<unit.getName()<<"-----"<<endl;
}
/*释放前vector的容量*/
cout<<"释放前vector的容量"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl; /*释放*/
vecStr.clear();
cout<<endl<<"clear后vector的容量"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl; /*swap*/
vector<CUnit>().swap(vecStr);
cout<<endl<<"swap后vector的容量"<<endl; cout<<"vecStr.size() :"<<vecStr.size()<<endl;
cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl; system("pause");
return ;
}

2.list的清内存

 class CUnit
{
private:
/* data */
string m_name;
public: CUnit(string name)
{
m_name = name;
//cout<<this<<",create"<<endl;
}
~CUnit()
{
//delete member
cout<<this<<",destroy"<<endl;
}
CUnit(const CUnit & c)
{
//cout<<&c<<",param"<<endl;
//cout<<this<<",copy"<<endl;
}
string getName(){cout<<this<<",copy"<<endl;return m_name;}
}; int main()
{
list<CUnit*> listStr;
CUnit *cUnit1 = new CUnit("Robb");
listStr.push_back(cUnit1); //此处调用复制构造函数 cout<<"push one"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl; CUnit* cUnit2 = new CUnit("Bran");//size不够,多次复制构造
listStr.push_back(cUnit2); cout<<"push two"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl;
CUnit *cUnit3 = new CUnit("Snow");//size不够,多次复制构造
listStr.push_back(cUnit3);
CUnit *cUnit4 = new CUnit("Arya");//size不够,多次复制构造
listStr.push_back(cUnit4);
CUnit *cUnit5 = new CUnit("Sansa");//size不够,多次复制构造
listStr.push_back(cUnit5); cout<<"push five"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl;
cout<<endl; /*打印*/
for(list<CUnit*>::iterator it = listStr.begin(); it!=listStr.end();it++)
{
cout<<"-----"<<(*it)->getName()<<"-----"<<endl;
}
/*释放前list的容量*/
cout<<"释放前list的容量"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
#if 1 //调用析构函数,清掉了list的内存
for(list<CUnit*>::iterator it = listStr.begin(); it!=listStr.end();)
{
delete *it;
listStr.erase(it++);
//cout<<"-----"<<(*it)->getName()<<"-----"<<endl;
} cout<<"释放后list的容量"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
#endif #if 0 //并不会调用析构函数,只是清掉了list的内存
/*释放*/
listStr.clear();
cout<<endl<<"clear后list的容量"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl; /*swap*/
cout<<endl<<"swap后list的容量"<<endl;
cout<<"listStr.size() :"<<listStr.size()<<endl;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
#endif
system("pause");
return ;
}

①自己new的空间,自己delete,然后再释放容器。

②不是new出来的,直接erase、remove和clear即可。这类链式存储,一个元素一个元素递增空间的结构,这些函数可以真正地改变list占用的内存大小。

感觉好多东西啊!今天的结束了!

参考文献:

https://www.cnblogs.com/EE-NovRain/archive/2012/06/12/2546500.html

https://philoscience.iteye.com/blog/1456509

https://blog.csdn.net/a272846945/article/details/51182144

https://blog.csdn.net/HW140701/article/details/76704583

C++——STL内存清除的更多相关文章

  1. STL 内存释放

    C++ STL 中的map,vector等内存释放问题是一个很令开发者头痛的问题,关于 stl内部的内存是自己内部实现的allocator,关于其内部的内存管理本文不做介绍,只是 介绍一下STL内存释 ...

  2. C++STL内存管理方法(g++版)

    STL作为C++的经典作品,一直备受人们关注.本文主要介绍STL的内存管理策略. 早期的STL内存管理 第一次接触STL源码是看侯捷先生的<STL源码剖析>,此书通俗易懂,剖析透彻,是极佳 ...

  3. STL内存配置器

    一.STL内存配置器的总体设计结构 1.两级内存配置器:SGI-STL中设计了两级的内存配置器,主要用于不同大小的内存分配需求,当需要分配的内存大小大于128bytes时, 使用第一级配置器,否则使用 ...

  4. STL内存分配

    STL内存创建 Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu  转载请标明来源 1.      Stl内存创建基类模板__malloc_alloc_tem ...

  5. STL内存管理

    1. 概述 STL Allocator是STL的内存管理器,也是最低调的部分之一,你可能使用了3年stl,但却不知其为何物. STL标准如下介绍Allocator the STL includes s ...

  6. STL—内存的配置与释放

    上一篇我们介绍了STL对象的构造与析构,这篇介绍STL内存的配置与释放. STL有两级空间配置器,默认是使用第二级.第二级空间配置器会在某些情况下去调用第一级空间配置器.空间配置器都是在allocat ...

  7. SGI STL内存配置器存在内存泄漏吗?

    阅读了SGI的源码后对STL很是膜拜,很高质量的源码,从中学到了很多.温故而知新!下文中所有STL如无特殊说明均指SGI版本实现. STL 内存配置器 STL对内存管理最核心部分我觉得是其将C++对象 ...

  8. C++技术问题总结-第8篇 STL内存池是怎么实现的

    STL内存池机制,使用双层级配置器.第一级採用malloc.free,第二级视情况採用不同策略. 这样的机制从heap中要空间,能够解决内存碎片问题. 1.内存申请流程图     简要流程图例如以下. ...

  9. C++STL内存配置的设计思想与关键源码分析

    说明:我认为要读懂STL中allocator部分的源码,并汲取它的思想,至少以下几点知识你要了解:operator new和operator delete.handler函数以及一点模板知识.否则,下 ...

随机推荐

  1. 第2次作业 -- 熟悉 JUnit 测试

    2.1 Mooctest 使用心得 Mooctest很方便,可以即时测评自己写的测试代码,获得覆盖率和报告,不需要自己安装配置环境 而且安装配置插件的环境也很简单,可以专注于测试本身 2.2 Juni ...

  2. xenserver添加磁盘后挂载为本地存储库并且删除

    方法一: 1.1:查看磁盘列表 fdisk -l [root@xenserver ~]# fdisk -l Disk /dev/sdb: 7999.4 GB, 7999376588800 bytes, ...

  3. url参数解析 and 日期格式化

    ~function (pro) { //url解析 function queryURLParameter() { var reg = /([^?&=#]+)=([^?&=#]+)/g, ...

  4. 获取百度地图POI数据一(详解百度返回的POI数据)

    POI是一切可以抽象为空间点的现实世界的实体,比如餐馆,酒店,车站,停车场等.POI数据具有空间坐标和各种属性,是各种地图查询软件的基础数据之一.百度地图作为国内顶尖的地图企业,其上具有丰富的POI数 ...

  5. 【leetcode198 解题思路】动态规划

    动态规划 https://blog.csdn.net/so_geili/article/details/53639920 最长公共子序列 https://blog.csdn.net/so_geili/ ...

  6. elasticsearch的监控脚本

    监控elasticsearch cluster 集群 通过主动模式将数据发送给zabbix server import json import struct import socket import ...

  7. windows下端口占用处理工具

    一.通用方法 经常,我们在启动应用的时候发现系统需要的端口被别的程序占用,笔者在最近使用tomcat时,老是会遇到这种端口占用的问题,如何知道谁占有了我们需要的端口,很多人都比较头疼,以下是通用方法: ...

  8. Wpf binging (二) 集合绑定

    除去简单控件的数据绑定,还有集合控件的数据绑定,一下示例 这发现 source 变成了 itemsSource   Path 变成了   DisplayMemberPath itemsSource:代 ...

  9. org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.zhuoshi.entity.Dep#1]

    报错信息: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.zhuoshi.e ...

  10. 类 __getitem__ __getattr__ __call__

    __getitem__ 实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,要表现得像list那样按照下标取出元素,需要实现__getitem__()方法 __g ...