眾所周知,auto_ptr是c++自動釋放指標,能確保new出來的記憶體能夠delete釋放,無論是正常退出還是異常退出。
博主做某個專案把new後的指標放在vector,感覺之後挨個delete有點麻煩,便想到能否vector存入auto_ptr,不用去操心釋放記憶體的事情。事情往往不如人願。g++一遍果斷報錯了。
博主寫了段測試**,如下:
1 #include 2 #include 3 #include 4 #include 5using
namespace
std;
6classb9
virtual ~b()
10virtual
void
print()
13};
14class a:public
b17 ~a()
20virtual
void
print()
23};
24void
main ()
25
後面經過資料的查詢,發現auto_ptr之所以不能用作容器的元素,是因為它的轉移語義,不符合容器對元素的要求。關於轉移語義,在此做個小小的解釋:
轉移語義可以將資源 ( 堆,系統物件等 ) 從乙個物件轉移到另乙個物件,這樣能夠減少不必要的臨時物件的建立、拷貝以及銷毀,能夠大幅度提高 c++ 應用程式的效能。臨時物件的維護 ( 建立和銷毀 ) 對效能有嚴重影響。轉移語義是和拷貝語義相對的,可以模擬檔案的剪下與拷貝,當我們將檔案從乙個目錄拷貝到另乙個目錄時,速度比剪下慢很多。通過轉移語義,臨時物件中的資源能夠轉移其它的物件裡。
詳細請參考該網頁:
為了驗證該論點,作者寫了一下**進行驗證:
1 #include 2 #include 3using
namespace
std;
4classb7
virtual ~b()8};
9class
a13 ~a()
14};
15int
main ()
16//
p2為區域性變數,出棧時執行起析構函式,其中將a類物件釋放掉。
21 cout<<"
after p2
"<2225 cout<<"
after p3
"<26return0;
27 }
執行結果如下:
a isdiscontructed
b is
discontructed
after p2
after p3
可以看出,在p轉移給p2的時候,p本身已經不存有new a()指標的所有權了。釋放記憶體的責任也丟給了p2。
那麼如何在容器中使用智慧型指標呢?可以使用boost庫中的shared_ptr智慧型指標,它會記錄有多少個shared_ptr共同指向乙個物件。這便是所謂的引用計數(reference counting)。一旦最後乙個這樣的指標被銷毀,也就是一旦某個物件的引用計數變為0,這個物件會被自動刪除。這在非環形資料結構中防止資源洩露很有幫助。
以下是在vector中使用shared_ptr**:
1 #include 2 #include3 #include 4using
namespace
std;
5using
namespace
boost;
6classa9
virtual ~a()
10};
1112
intmain()
19 cout<<"
after for function
"<20 }
執行結果如下:
after forfunction
a is
discontructed
a is
discontructed
a is
discontructed
a is
discontructed
a is discontructed
分析執行結果可以得知,容器中的物件是在19行執行結束後執行析構函式的。而不是在for函式中。
同樣,讀者可以試下發生異常能否執行析構函式。
最後總結:shared_ptr智慧型指標給了我們很多方便的地方,不用去考慮去delete釋放記憶體。盡可能使用智慧型指標,對記憶體洩露say bye~
wind
2013-11-21
由vector造成的物件切片問題
由vector造成的物件切片 在編寫乙個小例項的時候,發現用vector存放基類,而試圖呼叫子類的虛函式是行不通的!如下 這樣的結果是我當初的構想完全不一樣的,那麼為什麼會造成這種現象呢?先從物件大小的角度來看 由於宣告的是vector,那麼每個元素的大小就是sizeof base 如果轉入的是子類...
新建的WebService無法由Ajax呼叫
症狀 老是會提示無法找到物件。解決方法 預設的webservice引入了下列的命名空間 using system using system.data using system.web using system.collections using system.web.services using s...
PostgreSQL擴充套件無法加入到php中
當我們遇到這種情況,可能最簡單是編譯安裝擴充套件外掛程式,然後更改php.ini加入這個擴充套件,但是有時會遇到種種不可控的錯誤.這個時候,最簡單的是我們將php解除安裝掉.然後先安裝postgresql,在編譯php的時候再 configure with pgsql usr local progr...