c++实现一个简单的空间配置器allocator

c++实现一个简单的空间配置器allocator


      c++中内存分配和对象构造是分开来的,内存的分配类似malloc函数在内存空间开辟一段空间,但是里面不保存任何数据。对象的构造相当于给这段空间复制。


      这么做的理由有两点:

  •       在预先分配的内存中构造对象很浪费,可能创建从不使用的对象,当实际使用预先分配的对象时,被使用的对象往往又必须重新赋以新值。
  •       如果预分配的内存必须被构造,某些类就不能使用它。(?不理解)


      C++中内存分配一般有三个层次:

  1. 使用new创建对象, delete删除对象
  2. 使用allocator分配未初始化的内存,使用construct和destroy构造和析构对象
  3. 使用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);
}



你可能感兴趣的:(STL,内存分配,allocator,空间配置器)