C++——STL內存清除


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM