深入理解C 11(十二)

2021-10-13 13:02:53 字數 3094 閱讀 2253

改進物件池模式

物件池對於建立開銷比較大的物件來說很有意義,為了避免重複建立開銷比較大的物件,可以通過物件池來優化。物件池的思路比較簡單,事先建立好一批物件,放到乙個集合中,每當程式需要新的物件時,就從物件池中獲取,程式用完該物件後都會把該物件歸還給物件池。這樣會避免重複建立物件,提高程式效能。物件池的實現如**清單8-12所示。

#include

#include

#include

#include

using

namespace std;

const

int maxobjectnum =10;

template

<

typename t>

class

objectpool

~objectpool()

// 預設建立多少個物件

template

<

typename..

. args>

void

init

(size_t num, args&&..

. args)))

;}}template

<

typename t,

typename..

. args>

std::shared_ptr

createptr

(std::string& constructname, args.

.. args));

}// 從物件池中獲取乙個物件

template

<

typename..

. args>

std::shared_ptr

get(

)return

nullptr;}

private

:std::multimap> m_object_map;

bool needclear;};

這個物件池的實現很典型:初始建立一定數量的物件,用的時候直接從

池中取,用完之後再**到池子。

一般物件池的實現思路和這個類似,這種實現方式雖然能達到目的,但是存在以下不足:

1)物件用完之後需要手動**,用起來不夠方便,更大的問題是存在忘

記**的風險。

2)不支援引數不同的建構函式。

通過c++11可以解決這兩個問題:

1)對於第乙個問題,通過自動**用完的物件來解決。這裡用智慧型指標

就可以解決,在建立智慧型指標時可以指定刪除器,在刪除器中不刪除物件,

而是將其**到物件池中。這個過程對外界來說是看不見的,由智慧型指標自

己完成。

2)對於第二個問題,通過可變引數模板來解決。可變引數模板可以支援

不同引數的建構函式來建立物件。

物件池的實現如**清單8-13所示:

#include

#include

#include

#include

#include

"noncopyable.hpp"

usingnamespace std;

const

int maxobjectnum =10;

template

classobjectpool : noncopyable))

;}}// 從物件池中獲取乙個物件

template

<

typename..

. args>

std::shared_ptr

get(

)return

nullptr;}

private

:multimap> m_object_map;

};

測試**如**清單8-14所示:

#include

struct bigobject

bigobject

(int a)

bigobject

(const

int& a,

const

int& b)

void

print

(const string& str)};

void

print

(shared_ptrp,

const string& str)

}void

testobjpool()

// 出了作用域之後,物件池返回出來的物件又會自動**

auto p = pool.

get();

auto p2 = pool.

get();

print

(p,"p");

print

(p2,

"p2");

// 物件池支援過載建構函式

pool.

init(2

,1);

auto p4 = pool.get<

int>()

;print

(p4,

"p4");

pool.

init(2

,1,2

);auto p5 = pool.get<

int,

int>()

;print

(p5,

"p5");

}int

main()

輸出結果如下:pp2

pp2p4p5

在上述測試**中,設定了物件池的最大容量為2,所以在獲取p3時,將獲得乙個空指標。在離開作用域之後物件就被物件池**,後面就能再獲取池中的物件了。這裡需要注意的是,物件被**之後它的狀態並沒有被清除,使用者從池中獲取物件之後最好先初始化或重置一下狀態。p4和p5是不同建構函式建立的物件。需要注意的是,在物件池中建立不同的物件時,建構函式入參的引用將被忽略,即入參int和int&的建構函式會被認為是同一種型別的建構函式,因為在構造物件時無法獲取變參args…的引用型別,丟失了引用相關的資訊。

相比傳統的實現方式,改進之後的物件池的實現不僅能自動**物件,還能支援引數不同的建構函式,更加靈活和強大。

深入理解C 11(九)

move語義 我們知道移動語義是通過右值引用來匹配臨時值的,那麼,普通的左值是否也能借助移動語義來優化效能呢,那該怎麼做呢?事實上c 11為了解決這個問題,提供了std move方法來將左值轉換為右值,從而方便應用移動語義。move是將物件的狀態或者所有權從乙個物件轉移到另乙個物件,只是轉移,沒有記...

深入理解C 11(十五)

emplace back減少記憶體拷貝和移動 emplace back能就地通過引數構造物件,不需要拷貝或者移動記憶體,相比push back能更好地避免記憶體的拷貝與移動,使容器插入元素的效能得到進一步提公升。在大多數情況下應該優先使用emplace back來代替push back。所有的標準庫...

深入理解C 11(十六)

unordered container無序容器 c 11增加了無序容器unordered map unordered multimap和unordered set unordered multiset,由於這些容器中的元素是不排序的,因此,比有序容器map multimap和set multiset...