1. 程式人生 > >【C++11】實現物件池

【C++11】實現物件池

物件池

物件池顧名思義,就是存放一堆物件的池,目前一般的實現方式大多都是如下思路:

  1. 初始化建立一些系列(或者從外部載入)
  2. 從物件池取出一個物件使用
  3. 用完之後返回物件池

物件池有很多場景都可以使用,例如:一個物件構造很消耗時間,又或者一些物件被很頻繁的使用,都可以使用物件池。它的思想類似於資料庫連線池、網路控制代碼連線池等等。

在C++中藉助智慧指標,可以很方便的實現一個物件池,智慧指標可以自定義刪除器,在智慧指標需要釋放的時候呼叫刪除器,將物件重新放入物件池。
這裡關鍵要注意:

  1. 自定義刪除器
  2. shared_ptr或者unique_ptr

細節

  • 自定義刪除器只做一件事,就是將物件重新放入物件池。如果物件池初始化的時候就自定義刪除器的話,刪除器中的邏輯是將物件放回物件池,放回的時候無法再定義一個這樣的刪除器,所以這種做法行不通。

  • 需要注意,回收的物件只能是預設刪除器的。除了前述原因之外,另外一個原因是物件池釋放的時候需要釋放所有的智慧指標,釋放的時候如果存在自定義刪除器將會導致物件無法刪除。

  • 只有在get的時候定義刪除器才行,但是初始建立或加入的智慧指標是預設刪除器,所以我們需要把智慧指標的預設刪除器改為自定義刪除器。

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

程式碼實現

template<class T>
class SimpleObjectPool
{
public:
    using DelType = std::function<void(T*)>;

    void add(std::unique_ptr<T> t)
    {
        m_pool.push_back(std::move(t));
    }

    std::unique_ptr<T, DelType> get()
    {
        if (m_pool.empty())
        {
            throw
std::logic_error("no object"); } //every time add custom deleter for default unique_ptr std::unique_ptr<T, DelType> ptr(m_pool.back().release(), [this](T* t) { m_pool.push_back(std::unique_ptr<T>(t)); //刪除函式執行的操作 }); m_pool.pop_back(); //刪除最後一個被釋放的unique_ptr return std::move(ptr); } bool empty() const { return m_pool.empty(); } int size() const { return m_pool.size(); } private: std::vector<std::unique_ptr<T>> m_pool; }; //測試物件 struct STA { STA() { cout << "create" << endl; } STA(int i) { a = i; cout << "create int" << endl; } STA(const STA& other) { *this = other; cout << "copy" << endl; } ~STA() { cout << "delete" << endl; } int a = 0; }; //測試程式碼 void testPool() { SimpleObjectPool<STA> pool; pool.add(std::unique_ptr<STA>(new STA())); pool.add(std::unique_ptr<STA>(new STA())); { auto ptr = pool.get(); pool.get(); cout <<"pool size:"<< pool.size() << endl; } cout << "pool size:" << pool.size() << endl; { pool.get(); pool.get(); cout << "pool size:" << pool.size() << endl; } cout << "pool size:" << pool.size() << endl; }

輸出如下:
這裡寫圖片描述