国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

深度剖析C++對象池自動回收技術實現

2020-01-26 13:33:49
字體:
來源:轉載
供稿:網友

對象池可以顯著提高性能,如果一個對象的創建非常耗時或非常昂貴,頻繁去創建的話會非常低效。對象池通過對象復用的方式來避免重復創建對象,它會事先創建一定數量的對象放到池中,當用戶需要創建對象的時候,直接從對象池中獲取即可,用完對象之后再放回到對象池中,以便復用。這種方式避免了重復創建耗時或耗資源的大對象,大幅提高了程序性能。本文將探討對象池的技術特性以及源碼實現。

對象池類圖

ObjectPool:管理對象實例的pool。

Client:使用者。

適用性:

類的實例可重用。

類的實例化過程開銷較大。

類的實例化的頻率較高。

效果:

節省了創建類實例的開銷。

節省了創建類實例的時間。

存儲空間隨著對象的增多而增大。

問題

目前縱觀主流語言的實現方式無外乎3個步驟:

初始創建一定數量的對象池(也允許從外面添加對象)。

從對象池中取對象來使用。

用完之后返回對象池。

一般情況下這樣是OK的,可能存在的問題是在第三步,有兩個問題:

不方便,每次都需要顯式回收對象。

忘記將對象放回對象池,造成資源浪費。

改進動機

解決顯式回收的問題,實現自動回收,省心省力。改進之后的對象池無須提供release方法,對象會自動回收,改進之后的類圖如下。

技術內幕

借助c++11智能指針,因為智能指針可以自定義刪除器,在智能指針釋放的時候會調用刪除器,在刪除器中我們將用完的對象重新放回對象池。思路比較簡單,但實現的時候需要考慮兩個問題:

什么時候定義刪除器?以及用shared_ptr還是unique_ptr?下面我們一起來看一下: 

1. 什么時候定義刪除器

自定義刪除器只做一件事,就是將對象重新放入對象池。如果對象池初始化的時候就自定義刪除器的話,刪除器中的邏輯是將對象放回對象池,放回的時候無法再定義一個這樣的刪除器,所以這種做法行不通。需要注意,回收的對象只能是默認刪除器的。除了前述原因之外,另外一個原因是對象池釋放的時候需要釋放所有的智能指針,釋放的時候如果存在自定義刪除器將會導致對象無法刪除。只有在get的時候定義刪除器才行,但是初始創建或加入的智能指針是默認刪除器,所以我們需要把智能指針的默認刪除器改為自定義刪除器。

2 .用shared_ptr還是unique_ptr

因為我們需要把智能指針的默認刪除器改為自定義刪除器,用shared_ptr會很不方便,因為你無法直接將shared_ptr的刪除器修改為自定義刪除器,雖然你可以通過重新創建一個新對象,把原對象拷貝過來的做法來實現,但是這樣做效率比較低。而unique_ptr由于是獨占語義,提供了一種簡便的方法方法可以實現修改刪除器,所以用unique_ptr是最適合的。

2.實現源碼

#pragma once#include <memory>#include <vector>#include <functional>template <class T>class SimpleObjectPool{public:  using DeleterType = std::function<void(T*)>;  void add(std::unique_ptr<T> t)  {    pool_.push_back(std::move(t));  }  std::unique_ptr<T, DeleterType> get()  {    if (pool_.empty())    {      throw std::logic_error("no more object");    }    //every time add custom deleter for default unique_ptr    std::unique_ptr<T, DeleterType> ptr(pool_.back().release(), [this](T* t)    {      pool_.push_back(std::unique_ptr<T>(t));    });    pool_.pop_back();    return std::move(ptr);  }  bool empty() const  {    return pool_.empty();  }  size_t size() const  {    return pool_.size();  }private:  std::vector<std::unique_ptr<T>> pool_;};//test codevoid test_object_pool(){  SimpleObjectPool<A> p;  p.add(std::unique_ptr<A>(new A()));  p.add(std::unique_ptr<A>(new A()));  {    auto t = p.get();    p.get();  }  {    p.get();    p.get();  }  std::cout << p.size() << std::endl;}

如果你堅持用shared_ptr,那么回收的時候你需要這樣寫:

std::shared_ptr<T> get(){if (pool_.empty()){throw std::logic_error("no more object");}std::shared_ptr<T> ptr = pool_.back();auto p = std::shared_ptr<T>(new T(std::move(*ptr.get())), [this](T* t){pool_.push_back(std::shared_ptr<T>(t));});//std::unique_ptr<T, DeleterType> ptr(pool_.back().release(), [this](T* t)//{// pool_.push_back(std::unique_ptr<T>(t));//});pool_.pop_back();return p;}

這種方式需要每次都創建一個新對象,并且拷貝原來的對象,是一種比較低效的做法。代碼僅僅是為了展示如何實現自動回收對象,沒有考慮線程安全、對象池擴容策略等細節,源碼鏈接:object_pool

小結

凡是需要自動回收的場景下都可以使用這種方式:在獲取對象的時候將默認刪除器改為自定義刪除器,確保它可以回收。注意,回收的智能指針使用的是默認刪除器,可以確保對象池釋放時能正常釋放對象。同時也將獲取對象和釋放對象時,對象的控制權完全分離。其他的一些應用場景:多例模式,無需手動釋放,自動回收。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網的支持。如果你想了解更多相關內容請查看下面相關鏈接

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长宁区| 怀远县| 关岭| 介休市| 南郑县| 绵阳市| 黄陵县| 杨浦区| 红原县| 孟津县| 化州市| 文成县| 嘉禾县| 乌兰察布市| 巴彦淖尔市| 梓潼县| 麦盖提县| 锦屏县| 平山县| 江西省| 长兴县| 肇州县| 连山| 乌什县| 全南县| 金湖县| 安仁县| 关岭| 莫力| 江山市| 东方市| 青冈县| 长春市| 松滋市| 鲁甸县| 若尔盖县| 兰考县| 萨迦县| 上蔡县| 新巴尔虎左旗| 西城区|