MSVC++ 對象內存模型深入解析與具體應用
前言:本文之所以強調MSVC, 旨在提醒讀者在不同平臺和解釋器下內存布局和實現上存在差異,但編程思想通用,文中內容大多來自筆者實際工作經驗和網上搜集,力求正確,但水平有限,如有不當之處,敬請指出
面向對象:本文面向有一定C/C++基礎,并且可以讀懂部分匯編的讀者
版權:歡迎轉載,但請注明出處http://www.shnenglu.com/dawnbreak/, 保留對本文的一切權力
目錄
1. C++基本類型與結構體內存布局
Key words: class, struct, memory alignment
2.虛表, 多態與動態綁定
Key words: Virtual Table, polymiorphism
3.對象池
Key words: object pool , reload, new ,delete
4.內存泄漏檢測
Key words: memory leak detect
5.智能指針
Key words: smart pointer
6. 編譯期類型約束
Key words: compile-time ,type-constraint
第三章 對象池
Key words: object pool
對象池
對象池是一種避免在整個程序生存周期內重復創建或刪除大量對象的方法。在代碼里無論何時當你需要一個對象時,你可以在對象池中申請一個。當你使用完畢后,將其歸還到池中。對象池僅僅創建一次對象,所以他們的構造函數僅僅被調用一次,并不是每次使用時都調用。所以在對象池創建時僅僅做一些通用的初始化,而在對象實例調用其他非構造函數時進行特別賦值及操作。
一個對象池的實現
1
#include <queue>
2
#include <vector>
3
#include <stdexcept>
4
#include <memory>
5
using std::queue;
6
using std::vector;
7
//
8
// template class ObjectPool
9
//
10
// Provides an object pool that can be used with any class that provides a
11
// default constructor
12
//
13
// The object pool constructor creates a pool of objects, which it hands out
14
// to clients when requested via the acquireObject() method. When a client is
15
// finished with the object it calls releaseObject() to put the object back
16
// into the object pool.
17
//
18
// The constructor and destructor on each object in the pool will be called only
19
// once each for the lifetime of the program, not once per acquisition and release.
20
//
21
// The primary use of an object pool is to avoid creating and deleting objects
22
// repeatedly. The object pool is most suited to applications that use large
23
// numbers of objects for short periods of time.
24
//
25
// For efficiency, the object pool doesn’t perform sanity checks.
26
// It expects the user to release every acquired object exactly once.
27
// It expects the user to avoid using any objects that he or she has released.
28
//
29
// It expects the user not to delete the object pool until every object
30
// that was acquired has been released. Deleting the object pool invalidates
31
// any objects that the user has acquired, even if they have not yet been released.
32
//
33
template <typename T>
34
class ObjectPool
35

{
36
public:
37
//
38
// Creates an object pool with chunkSize objects.
39
// Whenever the object pool runs out of objects, chunkSize
40
// more objects will be added to the pool. The pool only grows:
41
// objects are never removed from the pool (freed), until
42
// the pool is destroyed.
43
//
44
// Throws invalid_argument if chunkSize is <= 0
45
//
46
ObjectPool(int chunkSize = kDefaultChunkSize)
47
throw(std::invalid_argument, std::bad_alloc);
48
//
49
// Frees all the allocated objects. Invalidates any objects that have
50
// been acquired for use
51
//
52
~ObjectPool();
53
//
54
// Reserve an object for use. The reference to the object is invalidated
55
// if the object pool itself is freed.
56
//
57
// Clients must not free the object!
58
//
59
T& acquireObject();
60
//
61
// Return the object to the pool. Clients must not use the object after
62
// it has been returned to the pool.
63
//
64
void releaseObject(T& obj);
65
protected:
66
//
67
// mFreeList stores the objects that are not currently in use
68
// by clients.
69
//
70
queue<T*> mFreeList;
71
//
72
// mAllObjects stores pointers to all the objects, in use
73
// or not. This vector is needed in order to ensure that all
74
// objects are freed properly in the destructor.
75
//
76
vector<T*> mAllObjects;
77
int mChunkSize;
78
static const int kDefaultChunkSize = 10;
79
//
80
// Allocates mChunkSize new objects and adds them
81
// to the mFreeList
82
//
83
void allocateChunk();
84
static void arrayDeleteObject(T* obj);
85
private:
86
// Prevent assignment and pass-by-value.
87
ObjectPool(const ObjectPool<T>& src);
88
ObjectPool<T>& operator=(const ObjectPool<T>& rhs);
89
};
template <typename T>
ObjectPool<T>::ObjectPool(int chunkSize) throw(std::invalid_argument,
std::bad_alloc) : mChunkSize(chunkSize)


{

if (mChunkSize <= 0)
{
throw std::invalid_argument(“chunk size must be positive”);
}
// Create mChunkSize objects to start.
allocateChunk();
}
//
// Allocates an array of mChunkSize objects because that’s
// more efficient than allocating each of them individually.
// Stores a pointer to the first element of the array in the mAllObjects
// vector. Adds a pointer to each new object to the mFreeList.
//
template <typename T>
void ObjectPool<T>::allocateChunk()


{
T* newObjects = new T[mChunkSize];
mAllObjects.push_back(newObjects);

for (int i = 0; i < mChunkSize; i++)
{
mFreeList.push(&newObjects[i]);
}
}
//
// Freeing function for use in the for_each algorithm in the
// destructor
//
template<typename T>
void ObjectPool<T>::arrayDeleteObject(T* obj)


{
delete [] obj;
}
template <typename T>
ObjectPool<T>::~ObjectPool()


{
// Free each of the allocation chunks.
for_each(mAllObjects.begin(), mAllObjects.end(), arrayDeleteObject);
}
template <typename T>
T& ObjectPool<T>::acquireObject()


{

if (mFreeList.empty())
{
allocateChunk();
}
T* obj = mFreeList.front();
mFreeList.pop();
return (*obj);
}
template <typename T>
void ObjectPool<T>::releaseObject(T& obj)


{
mFreeList.push(&obj);
}
以上是對象池的一個簡單實現,使用隊列mFreeList記錄可以使用的對象,使用向量mAllObjects來記錄所有的對象,以便安全釋放內存
在實際使用中,可以使用棧來保存可用對象,這樣可以更加高效的使用內存