內存:經常使用的是static memory 和stack memory。 static memory是用來存放local static objects、類中的靜態數據成員、定義在任何函數以外的變量(static中的變量在使用以前就已經分配了空間,並且其生命週期是整個程序的運行過程)。stack memory用來存放的是函數內部的非靜態變量(由於棧也叫函數調用棧,存放的是函數中的auto變量,函數退出時,須要將這些變量也從棧中清除,因此其中存儲的變量的生命週期只是在該函數中,所以必然存放的是該函數中的非靜態變量,固然還有函數返回地址,實參列表等)。這兩種內存是能夠自動的分配和回收的。 另外還有一種dynamic memory是用來動態內存分配的叫作heap(堆),heap中存儲的是在運行過程當中才分配內存的對象,其生命週期由程序負責控制(分配和釋放都是程序來完成,而非編譯器)
ios
一般在C++中申請和釋放動態內存(堆)使用的是一組關鍵字new和delete。可是,它們是有問題的,由於,一是很難保證空間在適當的時候被釋放了,二是有可能會去釋放仍然有其餘指針指向該內存的空間。
c++
library中在memory頭部定義了了兩個smart pointer來自動地管理動態內存。shared_ptr(還定義了一個weak_ptr), unique_ptr。smart pointer也和vector同樣是模板。用做類型建立對象的時候須要加上, 如shared_ptr p1; //shared_ptr that can point at a string
安全
shared_ptr: 容許多個指針指向相同的對象。最安全的方法是調用函數make_shared 進行分配。如shared_ptr p2 = make_shared(4). shared_ptr定義的建立的對象有一個指針reference count,不管何時拷貝shared_ptr的指針的時候,count都加1. 當給shared_ptr的指針賦了新值或者shared_ptr失效的時候,count減1。 當count等於0的時候,shared_ptr指向的對象自動釋放空間。因此關鍵是建立的對象中維持了一個引用計數,來追蹤全部指向該段空間的指針。若是計數的值爲0,表示沒有指針指向該對象,就釋放掉。函數
例如:this
auto r = make_shared<char>(4); r = q; //after this, system will release the four bytes memory.
爲何可以自動釋放內存: 必須提到constructor和destructor,constructor是分配內存,初始化對象的時候使用的,destructor是釋放空間,摧毀對象用的。在shared_ptr中有一個destructor,該destructor記錄了對象的引用計數,當引用計數爲0的時候,就釋放掉該對象的空間。spa
何時使用動態內存:指針
1)不知道要申請多少個對象(好比在一個for循環中,循環次數不必定)c++11
2)不知道對象的精確的類型(好比寫了一個模板函數)code
3) 須要在不一樣的對象之間共享數據(最經常使用的)orm
研究一下vector(stl中定義的一個容器)中使用的是哪裏的內存? 按照7的三個使用動態內存的條件,vector應該屬於不知道要多少空間來存放對象。所以,應該屬於動態內存方面的問題。 那麼應該如何地建立和釋放內存呢?vector中有兩個函數,size()和capacity(),size()表示容器中有多少個數據,capacity()表示容器中最多放置多少個數據。另外可使用clear來釋放容器中的數據。可是根據下面的實驗能夠看出,使用clear只是釋放掉了容器中的數據項,可是並無釋放容器佔有的空間。即容器在不斷地伸長地過程當中不斷地申請的新的空間並無釋放。仍然被這個容器佔用。可使用shrink_to_fit() 使得佔有的空間等於容器中實際的數據項,或者使用reserve(n)使得分配至少n的元素的空間。(可是根據C++ primer中所說,shrink_to_fit()只是一個請求,並不保證必定釋放掉空間,另外shrink_to_fit是在c++11中提出來的。 若是不支持C++11,可使用建立一個臨時的匿名容器再進行swap的方法來強制釋放掉空間,由於交換以後,臨時的匿名容器會當即被析構,而原來的容器則等於匿名容器的大小,也就是0)
#include <iostream> #include <vector> using namespace std; int main(){ vector it; double a[100] for(int i=0; i<100; i++){ a[i] = i; } cout << "數據項個數: " << it.size() << "容器佔有空間爲: " << it.capacity() << endl; for(int i=0;i<100;i++){ it.push_back(a[i]); } cout << ""數據項個數:" << it.size() << "容器佔有空間爲: " << it.capacity() << endl; it.clear(); cout << "clear以後數據項個數: " << it.size() << "clear以後容器佔有空間爲: " << it.capacity() << endl; it.shrink_to_fit(); //or vector().swap(it); cout << "swap以後數據項個數: " << it.size() << "swap以後容器佔有空間爲: " << it.capacity() << endl; return 0; }