程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Effective STL 第7條:如果容器中包含了通過new操作創建的指針,切記在容器對象析構前將指針delete掉

Effective STL 第7條:如果容器中包含了通過new操作創建的指針,切記在容器對象析構前將指針delete掉

編輯:關於C++

STL中的容器相當“聰明”,它們提供了迭代器,以便進行向後和向前的遍歷(通過begin、end、rbegin等);它們告訴你所包含的元素類型(通過它們的value_type類型定義);在插入和刪除的過程中,它們自己進行必要的內存管理;它們報告自己有多少對象,最多能容納多少對象(分別通過size和max_size);當然,當它們自身被析構時,它們自動析構所包含的每個對象。

有了這麼“聰明”的容器,許多程序員不再考慮自己做善後清理工作。更糟糕的是,他們認為,容器會考慮為他們做這些事情。很多情況下,他們是對的。但當容器包含的是new的方式而分配的指針時,他們這麼想就不正確了。沒錯,指針容器在自己被析構時會析構所包含的每個元素,但指針的“析構函數”不做任何事情!它當然也不會調用delete。

結果,下面的代碼直接導致資源洩露:

       void doSomething()
       {
             vectorvwp;
              for (int I = 0; I < SOME_MAGIC_NUMBER; ++i)
              {
                     Vwp.push_back(new Widget);
                     …
              }                                                //在這裡發生了Widget資源洩露
       }


當vwp的作用域結束時,它的元素全部被析構,但並沒有改變通過new創建的對象沒有被刪除這一事實。刪除這些對象是你的責任,不是vector的責任。這是vector的特性。只有你才知道這些指針是否應該被釋放。

	void doSomething()
	{
		for (vector::iterator I = vwp.begin(); i != vwp.end(); ++i)
			delete *i;
	}



這樣做能行,但只是在你對“能行“不那麼挑剔時。一個問題是,新的for循環做的事情和for_each相同,但不如使用for_each看起來那麼清楚。問題是,這段代碼不是異常安全的。如果在想vwp中填充指針和從中刪除指針的兩個過程中間有異常拋出的話,同樣會有資源洩露。

其一解決方法如下:

       struct DeleteObject
       {
              template
              void operator() (const T* ptr) const
              {
                     delete ptr;
              }
       };
       void doSomething()
       {
              deque dssp;
              for_each (dssp.begin(), dssp.end(), DeleteObject());
       }

但它仍然不是異常安全的。如果在SpecialString已經被創建而對for_each的調用還沒開始時就有異常被拋出,則會有資源洩露發生。

其二解決方法:

利用Boost庫中的shared_ptr。

       void doSomething()
       {
              typedef boost::shared_ptr SPW;   //SPW= “指向Widget的shared_ptr”
              vector vwp;
              for (int I = 0; I < SOME_MAGIC_NUMBER; ++i)
                     vwp.push_back(SPW(new Widget));
                     …
       }      //這裡不會有Widget洩露,即使在上面的代碼中有異常被拋出

永遠不要錯誤的認為:你可以通過創建auto_ptr的容器使指針被自動刪除。這個想法很危險,具體解釋請看Effective STL 第8條。

你要記住的是:STL容器很智能,但沒有智能到知道是否該刪除自己所包含的指針的程度。當你使用指針的容器,而其中的指針應該被刪除時,為了避免資源洩露,你必須或者用引用計數形式的智能指針對象(比如Boost的shared_ptr)代替指針,或者容器被析構時手工刪除其中的每個指針。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved