我自己写了一个简易的空间适配器代码如下,后来发现,不同类型的类模板共享的静态成员变量不是同一块。
这可以通过查看不同类型类模板静态成员的地址,地址相同,表示共享的是同一块,不同则表示不是同一块。
cout<<"address="<<&Second_alloc<char>::free_list[i]<<endl;
cout<<"address="<<&Second_alloc<int>::free_list[i]<<endl;
也就是说:类模板的静态成员变量是所有同类型的类模板实例共享的一块数据。
#include<iostream>
#include<cstddef>
using namespace std;
//第一级空间配置器
template<class T>
class First_alloc{
public:
static T *allocate(size_t size)
{
void *result = malloc(size * sizeof(T));
return (T *)result;
}
static void deallocate(void *p)
{
free(p);
}
};
//第二级空间配置器
template<class T>
class Second_alloc{
private:
enum{ ALIGN = 8, MAX_BYTES = 128, NUMBER = MAX_BYTES / ALIGN};
//将bytes调整为8的倍数
static size_t ROUND_UP(size_t bytes)
{
return ((bytes + ALIGN - 1) & ~ (ALIGN -1));
}
static int FREELIST_INDEX(size_t bytes)
{
return ((bytes + ALIGN -1) / ALIGN - 1 );
}
static char *start_free;
static char *end_free;
static char *refill(size_t n);
static char *chunk_alloc(size_t n, int& nobj);
public:
struct obj{
char *address;
obj *next;
};
static obj *free_list[NUMBER];
public:
static T *allocate(size_t n);
static void deallocate(void *p, int size);
};
template<class T>
typename Second_alloc<T>::obj *
Second_alloc<T>::free_list[NUMBER] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
template<class T>
char *Second_alloc<T>::start_free = 0;
template<class T>
char *Second_alloc<T>::end_free =0;
template<class T>
char * Second_alloc<T>::chunk_alloc(size_t n, int& nobj)
{
size_t bytes_to_need = n * nobj;
size_t bytes_left = end_free - start_free;
char *result;
if(bytes_left >= bytes_to_need)
{
result = start_free;
start_free += bytes_to_need;
return result;
}
else if(bytes_left >= n)
{
nobj = bytes_left/n;
bytes_to_need = n * nobj;
result = start_free;
start_free += bytes_to_need;
return result;
}
else
{
if(bytes_left > 0)
{
obj **my_free_list = free_list + FREELIST_INDEX(bytes_left);
obj * tmp = (obj *)start_free;
tmp->address = start_free;
tmp->next = *my_free_list;
*my_free_list = tmp;
}
start_free = (char *)malloc(bytes_to_need * 2);
result = start_free;
start_free += bytes_to_need;
end_free = start_free + bytes_to_need;
return chunk_alloc(n, nobj);
}
}
template<class T>
char * Second_alloc<T>::refill(size_t n)
{
int nobj = 20;
char *chunk = chunk_alloc(n, nobj);
char *result =chunk;
obj **my_free_list;
my_free_list = free_list + FREELIST_INDEX(n);
*my_free_list = (obj *)(chunk + n);
int i;
char *address = chunk + n;
obj *current_obj = *my_free_list;
for(i=1; ;i++)
{
current_obj->address = address;
if(nobj -1 == i)
{
current_obj->next = 0;
break;
}
else
{
current_obj->next = (obj *)(address + n);
address +=n;
current_obj = current_obj->next;
}
}
return result;
}
template<class T>
T *Second_alloc<T>::allocate(size_t n)
{
size_t total_bytes = sizeof(T) * n;
if(total_bytes > MAX_BYTES)
{
return First_alloc<T>::allocate(total_bytes);
}
else
{
obj **my_free_list;
obj *result;
my_free_list = free_list + FREELIST_INDEX(total_bytes);
result = *my_free_list;
if(result == 0)
{
result =(obj *) refill(ROUND_UP(total_bytes));
return (T *)result;
}
else
{
*my_free_list = result->next;
return (T *)result->address;
}
}
}
template<class T>
void Second_alloc<T>::deallocate(void *p, int n)
{
size_t size = sizeof(T) * n;
if(size> MAX_BYTES)
{
First_alloc<T>::deallocate(p);
}
else
{
obj **my_free_list = free_list + FREELIST_INDEX(size);
obj * result = (obj *)p;
result->address = (char *)p;
result->next = *my_free_list;
*my_free_list = result;
}
}
void main()
{
int i;
int size;
//分配10个整数空间
size = 10;
int * q = Second_alloc<int>::allocate(size);
int *int_head = q;
for(i = 0; i < size; i++)
{
*q = i;
q++;
}
int *int_start = int_head;
for(i = 0; i< size; i++)
{
cout<<*int_start<<endl;
int_start++;
}
cout<<"------------------------------------------------------------------"<<endl;
for(i = 0; i < 16; i++)
{
cout<<"--------"<<i<<"----------------"<<endl;
cout<<"address="<<&Second_alloc<int>::free_list[i]<<endl;
if(Second_alloc<int>::free_list[i] != 0)
{
Second_alloc<int>::obj * my_free_list = Second_alloc<int>::free_list[i];
while(1)
{
cout<<(int)my_free_list->address<<"-----"<<my_free_list->next<<"-----"<<endl;
if( my_free_list->next == 0)
break;
else
my_free_list = my_free_list->next;
}
}
}
//分配5个字符空间
size = 5;
char * p = Second_alloc<char>::allocate(size);
char * head = p;
for(i = 0; i < size; i++)
{
*p = (char)i;
p++;
}
char *start = head;
for(i = 0; i < size; i++)
{
cout<<*start<<endl;
start++;
}
//分配5个整数空间
size = 5;
q = Second_alloc<int>::allocate(size);
int_head = q;
for(i = 0; i < size; i++)
{
*q = i;
q++;
}
int_start = int_head;
for(i = 0; i< size; i++)
{
cout<<*int_start<<endl;
int_start++;
}
cout<<"------------------------------------------------------------------"<<endl;
for(i = 0; i < 16; i++)
{
cout<<"--------"<<i<<"----------------"<<endl;
cout<<"address="<<&Second_alloc<int>::free_list[i]<<endl;
if(Second_alloc<int>::free_list[i] != 0)
{
Second_alloc<int>::obj * my_free_list = Second_alloc<int>::free_list[i];
while(1)
{
cout<<(int)my_free_list->address<<"-----"<<my_free_list->next<<"-----"<<endl;
if( my_free_list->next == 0)
break;
else
my_free_list = my_free_list->next;
}
}
}
cout<<"------------------------------------------------------------------"<<endl;
for(i = 0; i < 16; i++)
{
cout<<"--------"<<i<<"----------------"<<endl;
cout<<"address="<<&Second_alloc<char>::free_list[i]<<endl;
if(Second_alloc<char>::free_list[i] != 0)
{
Second_alloc<char>::obj * my_free_list = Second_alloc<char>::free_list[i];
while(1)
{
cout<<(int)my_free_list->address<<"-----"<<my_free_list->next<<"-----"<<endl;
if( my_free_list->next == 0)
break;
else
my_free_list = my_free_list->next;
}
}
}
}