首页 > 系统相关 >c++ vector 正确释放内存

c++ vector 正确释放内存

时间:2024-05-28 20:10:50浏览次数:27  
标签:容量 clear c++ vector 内存 拷贝 swap

 

今天在看微博的时候, 有人提出了一个对于Vector内存泄露的疑问( Link)。

博主采用 Vector存储一些数据,但是发现在执行 clear() 之后内存并没有释放,于是怀疑产生了内存泄露。随后有人回复:

“vector 的 clear 不影响 capacity , 你应该 swap 一个空的 vector。”

开始并不知道回复者在说什么,于是在谷歌上搜索 vector swap clear 发现已经有类似的问题出现了,并且给出了一些解决方案。

原来这样的问题在 《Effective STL》中的“条款17”已经指出了

当vector、string大量插入数据后,即使删除了大量数据(或者全部都删除,即clear) 并没有改变容器的容量(capacity),所以仍然会占用着内存。 为了避免这种情况,我们应该想办法改变容器的容量使之尽可能小的符合当前 数据所需(shrink to fit)

《Effective STL》给出的解决方案是:

1 2 3 4 5 6 7 vector<type> v; //.... 这里添加许多元素给v //.... 这里删除v中的许多元素 vector<type>(v).swap(v); //此时v的容量已经尽可能的符合其当前包含的元素数量 //对于string则可能像下面这样 string(s).swap(s);

即先创建一个临时拷贝与原先的vector一致,值得注意的是,此时的拷贝 其容量是尽可能小的符合所需数据的。紧接着将该拷贝与原先的vector v进行 交换。好了此时,执行交换后,临时变量会被销毁,内存得到释放。此时的v即为原先 的临时拷贝,而交换后的临时拷贝则为容量非常大的vector(不过已经被销毁)

为了证明这一点,我写了一个程序,如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <iostream> #include <vector>   using namespace std;   vector <string> v; char ch;   int main () {        for ( int i=0; i<1000000; i++)          v.push_back( "abcdefghijklmn" );      cin >> ch;      // 此时检查内存情况 占用54M        v.clear();      cin >> ch;      // 此时再次检查, 仍然占用54M        cout << "Vector 的 容量为" << v.capacity() << endl;      // 此时容量为 1048576        vector<string>(v).swap(v);        cout << "Vector 的 容量为" << v.capacity() << endl;      // 此时容量为0      cin >> ch;      // 检查内存,释放了 10M+ 即为数据内存      return 0; }

总结

从这个事情说明,自己对STL的了解还非常的不够 平时对vector的清除都懂得采用 clear 方法。

另一方面 对于STL的设计思想也有些了解,在创建一个vector后 vector的实际容量一般会比给数据要大,这样做应该是避免过多的 重新分配内存吧。

当然,上面这种方法虽然释放了内存,但是同时也增加了拷贝数据的时间消耗。 不过一般需要重新调整容量的情况都是 vector本身元素较少的情况,所以 时间消耗可以忽略不计。

因此建议以后大家都将调用 clear() 改为 swap() 吧。

转自http://blog.jobbole.com/37700/

 

来自:

https://www.cnblogs.com/huojing/articles/16914992.html

标签:容量,clear,c++,vector,内存,拷贝,swap
From: https://www.cnblogs.com/rebrobot/p/18218757

相关文章

  • C++实现获取设备管理器中的设备信息
     C++实现获取设备管理器中的设备信息,基本调用了windowsAPI函数,除此之外,还引用了setupapi.lib库,代码如下所示://PrintDeviceInfo.cpp:定义控制台应用程序的入口点。//#include<stdio.h>#include<locale.h>#include<Windows.h>#include<setupapi.h>#pragmacomm......
  • C++实现删除打印机副本功能
     我们要实现此功能,首先需要获取到打印机的名称,其次是将获取到的打印机名称依次删除。一、获取打印机副本名称1.我们获取打印机副本名称,可以使用windowsAPI中的EnumPrinters函数,该函数可以枚举出我们电脑中的打印机设备信息,该函数使用方法如下:DWORDFlags=PRINTER_ENU......
  • C++实现dll文件的显示调用
    我们实现dll文件的显示调用,主要分为三个步骤:创建DLL、导出函数、使用DLL。其中离不开WindowsAPI函数,使用到了LoadLibrary、GetProcAddress、 FreeLibrary等,以下是一个简单的示例程展示整个过程。:1.创建DLLMyLibrary.h//MyLibrary.h#ifndefMY_LIBRARY_H#defineMY_LI......
  • C++跨平台库boost和Poco的编译
    PrerequisitesCMake3.5ornewerAC++17compiler(VisualC++2022,GCC8.0,Clang5,ornewer)在window下编译依赖的三方库编译POCO$gitclone-bmasterhttps://github.com/pocoproject/poco.git$cdpoco$mkdircmake-build$cdcmake-build$cmake..$cma......
  • C++17 链接 C++11 lib 出现重复定义
    C++11实现staticconstexpr是按照conststatic实现的,需要在.cpp中定义://tmp.hclassStatisTest{public:staticconstexprconstcharliteral[]="xxxliteral";};//tmp.cc#include"tmp.h"constcharStatisTest::literal[];//compile......
  • 3.1 内存中自动存储—3.4 mov、add、sub 指令
     第3章寄存器(内存访问)在第2章中,我们主要从CPU如何执行指令的角度讲解了8086CPU的逻辑结构、形成物理地址的方法、相关的寄存器以及一些指令。读者应在通过了前一章所有的检测点,并完成了实验任务之后,再开始学习当前的课程。本章中,我们将从访问内存的角度继续学习几个寄......
  • 阿赵UE引擎C++编程学习笔记——文件夹操作和文件读写
      大家好,我是阿赵。  这次学习一下在UE里面使用C++的API操作文件读写和文件夹操作。一、UE引擎获取相关路径  获取到路径一般是相对路径,使用FPaths::ConvertRelativePathToFull转换后,可以获得完整的绝对路径。FStringcontentDir=FPaths::ProjectContentDir();......
  • tomcat-设置jdk-设置标题-设置内存-配置项目路径
    tomcat目录下把jdk、项目包复制到根目录里 catalina.batsetTITLE=server[拜特接口平台服务端]#9000[%DATE%%TIME%]remsetJAVA_HOME=D:\Bytter_T2_test\jdk1.7.0_75setJAVA_HOME=..\jdk\jdk1.7.0_17setJRE_HOME=..\jdk\jre7setCATALINA_OPTS=-Xms512m-Xm......
  • 《C++primer》第八章课后习题
    练习8.1istream&abc(istream&is){ strings; is>>s; cout<<s; s.clear(); returnis;}练习8.2abc(cin);练习8.3答:输入类型与i不符,或者输入结束标识练习8.4vector<string>s;voidabc(strings1){ strings2; ifstreamin(s1); while(getline(......
  • 《C++primer》读书笔记---第八章:IO库
    8.1IO类下表列出的是一些IO类型:  为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵wchar_t类型的数据。宽字符版本的类型和函数的名字以一个w开始,例如,wcin、wcout、wcerr是分别对应cin、cout、cerr的宽字符类型。注:IO对象无拷贝或赋值ofstreamout1,out2;......