C++——STL内存清除

会有一股神秘感。 提交于 2020-12-18 08:42:12

1.vector元素的清除

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

 1 #include<iostream>
 2 #include<list>
 3 #include<vector>
 4 #include<iterator>
 5 #include<string>
 6 using std::vector;
 7 using std::list;
 8 using std::iterator;
 9 using std::string;
10 using std::cout;
11 using std::endl;
12 
13 int main()
14 {
15     vector<string> vecStr;
16     string pStr1 = "Robb";
17     vecStr.push_back(pStr1);
18     string pStr2 = "Bran";
19     vecStr.push_back(pStr2);
20     string pStr3 = "Snow";
21     vecStr.push_back(pStr3);
22     string pStr4 = "Sansa";
23     vecStr.push_back(pStr4);
24     string pStr5 = "Arya";
25     vecStr.push_back(pStr5);
26     
27     /*打印*/
28     for(auto unit:vecStr)
29     {
30         cout<<"-----"<<unit<<"-----"<<endl;
31     }
32     /*释放前vector的容量*/
33     cout<<"释放前vector的容量"<<endl;
34 
35     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
36     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
37 
38     /*释放*/
39     vecStr.clear();
40     cout<<endl<<"clear后vector的容量"<<endl;
41 
42     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
43     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
46     system("pause");
47     return 0;
48 }

输出结果如图:

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

我们加一下代码

1     /*swap*/
2     vector<string>().swap(vecStr);
3     cout<<endl<<"swap后vector的容量"<<endl;
4 
5     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
6     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,调用复制构造函数。

 

 1 class CUnit
 2 {
 3 private:
 4     /* data */
 5     string m_name;
 6 public:
 7 
 8     CUnit(string name)
 9     {
10         m_name = name;
11         //cout<<this<<",create"<<endl;
12     }
13     ~CUnit()
14     {
15         //delete member
16         cout<<this<<",destroy"<<endl;
17     }
18     CUnit(const CUnit & c)
19     {
20         //cout<<&c<<",param"<<endl;
21         //cout<<this<<",copy"<<endl;
22     } 
23     string& getName(){return m_name;}
24 };
25 
26 
27 int main()
28 {
29     vector<CUnit> vecStr;
30     CUnit cUnit1 = CUnit("Robb");
31     vecStr.push_back(cUnit1);    //此处调用复制构造函数
32     
33     cout<<"push one"<<endl;
34 
35     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
36     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
37 
38 
39     CUnit cUnit2 = CUnit("Bran");//size不够,多次复制构造
40     vecStr.push_back(cUnit2);
41         
42     cout<<"push two"<<endl;
43 
44     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
45     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
46     CUnit cUnit3 = CUnit("Snow");//size不够,多次复制构造
47     vecStr.push_back(cUnit3);    
48     CUnit cUnit4 = CUnit("Arya");//size不够,多次复制构造
49     vecStr.push_back(cUnit4);
50     CUnit cUnit5 = CUnit("Sansa");//size不够,多次复制构造
51     vecStr.push_back(cUnit5);
52     cout<<"push five"<<endl;
53     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
54     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
55     cout<<endl;
56     
57     /*打印*/
58     for(auto unit:vecStr)
59     {
60         cout<<"-----"<<unit.getName()<<"-----"<<endl;
61     }
62     /*释放前vector的容量*/
63     cout<<"释放前vector的容量"<<endl;
64 
65     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
66     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
67 
68     /*释放*/
69     vecStr.clear();
70     cout<<endl<<"clear后vector的容量"<<endl;
71 
72     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
73     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
74 
75     /*swap*/
76     vector<CUnit>().swap(vecStr);
77     cout<<endl<<"swap后vector的容量"<<endl;
78 
79     cout<<"vecStr.size()    :"<<vecStr.size()<<endl;
80     cout<<"vecStr.capacity():"<<vecStr.capacity()<<endl;
81 
82     system("pause");
83     return 0;
84 }

 

2.list的清内存

 1 class CUnit
 2 {
 3 private:
 4     /* data */
 5     string m_name;
 6 public:
 7 
 8     CUnit(string name)
 9     {
10         m_name = name;
11         //cout<<this<<",create"<<endl;
12     }
13     ~CUnit()
14     {
15         //delete member
16         cout<<this<<",destroy"<<endl;
17     }
18     CUnit(const CUnit & c)
19     {
20         //cout<<&c<<",param"<<endl;
21         //cout<<this<<",copy"<<endl;
22     } 
23     string getName(){cout<<this<<",copy"<<endl;return m_name;}
24 };
25 
26 
27 int main()
28 {
29     list<CUnit*> listStr;
30     CUnit *cUnit1 = new CUnit("Robb");
31     listStr.push_back(cUnit1);    //此处调用复制构造函数
32     
33     cout<<"push one"<<endl;
34     cout<<"listStr.size()    :"<<listStr.size()<<endl;
35 
36     CUnit* cUnit2 = new CUnit("Bran");//size不够,多次复制构造
37     listStr.push_back(cUnit2);
38         
39     cout<<"push two"<<endl;
40     cout<<"listStr.size()    :"<<listStr.size()<<endl;
41     CUnit *cUnit3 = new CUnit("Snow");//size不够,多次复制构造
42     listStr.push_back(cUnit3);    
43     CUnit *cUnit4 = new CUnit("Arya");//size不够,多次复制构造
44     listStr.push_back(cUnit4);
45     CUnit *cUnit5 = new CUnit("Sansa");//size不够,多次复制构造
46     listStr.push_back(cUnit5);
47 
48     cout<<"push five"<<endl;
49     cout<<"listStr.size()    :"<<listStr.size()<<endl;
50     cout<<endl;
51     
52     /*打印*/
53     for(list<CUnit*>::iterator it = listStr.begin(); it!=listStr.end();it++)
54     {
55         cout<<"-----"<<(*it)->getName()<<"-----"<<endl;
56     }
57     /*释放前list的容量*/
58     cout<<"释放前list的容量"<<endl;
59     cout<<"listStr.size()    :"<<listStr.size()<<endl;
60     cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
61 #if 1              //调用析构函数,清掉了list的内存
62     for(list<CUnit*>::iterator it = listStr.begin(); it!=listStr.end();)
63     {
64          delete *it;
65         listStr.erase(it++);
66         //cout<<"-----"<<(*it)->getName()<<"-----"<<endl;
67     }
68 
69     cout<<"释放后list的容量"<<endl;
70     cout<<"listStr.size()    :"<<listStr.size()<<endl;
71     cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
72 #endif
73 
74 #if 0              //并不会调用析构函数,只是清掉了list的内存
75     /*释放*/
76     listStr.clear();
77     cout<<endl<<"clear后list的容量"<<endl;
78     cout<<"listStr.size()    :"<<listStr.size()<<endl;
79     cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
80 
81     /*swap*/
82     cout<<endl<<"swap后list的容量"<<endl;
83     cout<<"listStr.size()    :"<<listStr.size()<<endl;
84     cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
85 #endif
86     system("pause");
87     return 0;
88 }

①自己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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!