c++實現一個簡單的空間配置器allocator
c++中內存分配和對象構造是分開來的,內存的分配類似malloc函數在內存空間開闢一段空間,但是裏面不保存任何數據。對象的構造相當於給這段空間複製。
這麼做的理由有兩點:
- 在預先分配的內存中構造對象很浪費,可能創建從不使用的對象,當實際使用預先分配的對象時,被使用的對象往往又必須重新賦以新值。
- 如果預分配的內存必須被構造,某些類就不能使用它。(?不理解)
C++中內存分配一般有三個層次:
- 使用new創建對象, delete刪除對象
- 使用allocator分配未初始化的內存,使用construct和destroy構造和析構對象
- 使用operator new分配內存,operator delete刪除內存,placement new創建對象,顯式調用析構函數析構對象
第一層:
當使用new表達式時,實際發生三個步驟。首先,該表達式調用名爲operator new的標準函數庫,分配足夠大的原始的未初始化的內存,以保存指定類型的一個對象;接下來,運行該類型的一個構造函數,用指定初始化式構造對象;最後,返回指向新分配並構造的對象的指針。
當使用delete的時候類似,先適當的析構,然後釋放內存 .
void main()
{
int *p=new int(10);
printf("%d",*p);
}
第二層
使用allocator類,它提供各種類型的內存分配和對象的構造與撤銷,allocator類講內存分配和對象構造分開。當allocator對象分配內存時,它分配適當大小並排列成保存給定類型對象的空間。但是,它分配的內存時未構造的,allocator的用戶必須分別使用construct和destory放置在改內存中的對象。
#include<iostream>
#include<memory> //使用allocator必須包含memory
using namespace std;
void main()
{
allocator<int> alloc;
int *ptr=alloc.allocate(1);
alloc.construct(ptr,10);
printf("%d\n",*ptr);
}
結果:
10
請按任意鍵繼續. . .
第三層
使用標準庫函數operator new和operator delete,使用它們可以獲得未構造的內存,下面的*p=10相當於構造函數.
#include<iostream>
using namespace std;
void main()
{
int *p=static_cast<int*>(operator new[](sizeof(int)));
*p=10;
}
使用placement new表示式來構造對象,指在已分配的原始內存中初始化一個對象,它不分配內存,只構造對象,它可以使用任何構造函數,並直接建立對象,相對於allocator中的construct就比較靈活,construct只能使用複製構造函數,這樣在進制使用複製構造函數的地方allocator是不能用的。
placement new的形式爲:
new (placae-address) type;
new(placae-address) type (initializer-list)
#include<iostream>
using namespace std;
void main()
{
int *p=static_cast<int*>(operator new[](sizeof(int)));
new (p) int(10);
}
再舉個類的例子
#include<iostream>
using namespace std;
class A
{
public:
int data;
};
void main()
{
A *ptr=static_cast<A*>(operator new[](sizeof(A)*2));
new (ptr) A;
printf("%d",(*ptr).data);
}
#include<iostream>
using namespace std;
//分配內存
template<typename T>
inline T* _allocate(unsigned int size,T*)
{
T* tmp=static_cast<T*>(operator new[](size*sizeof(T)));
if(tmp==0)
{
cout<<"'out of memory"<<endl;
exit(1);
}
return tmp;
}
//釋放內存
template<typename T>
inline void _deallocate(T* buffer)
{
operator delete(buffer);
}
//構造對象
template<typename T1,typename T2>
inline void _construct(T1 *p,const T2 &value)
{
new (p) T1(value);
}
//析構對象
template<typename T>
inline void _destory(T *ptr)
{
ptr->~T();
}
//我的空間配置器
template<typename T>
class myAllocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef unsigned int size_type;
template<typename U>
struct rebind
{
typedef allocator<U> other;
};
pointer allocate(size_type n,const void *hint=0)
{
return _allocate(n,(pointer)0);
}
void deallocate(pointer p,size_type n)
{
_deallocate(p);
}
void construct(pointer p,const T &value)
{
_construct(p,value);
}
void destroy(pointer p)
{
_destory(p);
}
};
//主函數,檢查正確性
void main()
{
myAllocator<int> alloc;
int *ptr=alloc.allocate(2);
alloc.construct(ptr,10);
printf("%d",*ptr);
}