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. sorry

    登录的时候密码忘了 重置了之后才登录上 这是有多久没登录了 好囧呀 近段时间学习Python也断断续续的 马上春节要到了 随后的20多天里 应该更没有时间学习了 想想都很忧伤 明明想很努力来着 但是总 ...

  2. Day-01

    昨天学习的内容都是一些简单的入门知识 like:二进制,编程语言这些 我觉得二进制还蛮好玩的 对于ascii码 还好,我不是很陌生 因为学函数的时候,老师有讲到这些 嗯 昨天就这些 继续加油~~~

  3. 对低开销的静态组件使用v-once

    <body> <div id="app"> <terms-of-service></terms-of-service> </d ...

  4. 汉诺塔问题-递归实现-JAVA

    public class hanio { /** * @param args */ public static void main(String[] args) { // TODO Auto-gene ...

  5. java 秒时间格式化

    public static String durationFormat(Integer totalSeconds) { if (totalSeconds == null || totalSeconds ...

  6. CentOS6.5 - yum对Mysql的安装与配置

    一.mysql的安装 1.查看是否安装mysql [root@localhost ~]# rpm -qa | grep mysql 如果有进行卸载(以下三种方式选一种即可): -.el6.x86_64 ...

  7. puts方法要点

    puts是print string的缩写.尽管没有直观的表示会调用换行符,但是puts会这样做:如同print,打印用户的数据,之后自动地转到新一行.假如让puts打印已经以换行符结束的一行,它不会再 ...

  8. springboot 之 连接数据库

    在连接数据库的时候,配置文件是这样写的,但是却一直报 java.sql.SQLException: Access denied for user 'root'@'localhost' (using p ...

  9. jdk环境变量配置改变不生效的问题

    在工作中两次遇到jdk配置上的这个问题:将环境变量中的jdk路径修改之后,使用-version查看,版本号还是之前的,也就是说修改未生效.甚至当我将Path变量中的jdk路径配置都删除了之后,使用-v ...

  10. 自定义注解(spring)

    终于有时间可以在这里写一篇博文了,今天写一下我在项目中用到的自定义注解,就是在每次操作项目的时候,想把它的操作加在我的数据库中,简单地说就是日志管理,这些东西都写完之后,我就问我自己,问什么要自定义注 ...