由vector中無法加入auto ptr所想到的

2022-03-31 04:43:39 字數 2311 閱讀 4028

眾所周知,auto_ptr是c++自動釋放指標,能確保new出來的記憶體能夠delete釋放,無論是正常退出還是異常退出。

博主做某個專案把new後的指標放在vector,感覺之後挨個delete有點麻煩,便想到能否vector存入auto_ptr,不用去操心釋放記憶體的事情。事情往往不如人願。g++一遍果斷報錯了。

博主寫了段測試**,如下:

1 #include 2 #include 3 #include 4 #include 5

using

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 3

using

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 is

discontructed

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 4

using

namespace

std;

5using

namespace

boost;

6classa9

virtual ~a()

10};

1112

intmain()

19 cout<<"

after for function

"<20 }

執行結果如下:

after for

function

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...