《C++标准程序库》小结第十五章-自定义空间配置器

第十四章是国际化议题,解决不同地区因为文化差异,产生的输入与输出问题。这对于我暂时没有用,而且还有更好的第三方库可以解决这个问题。

 

(1)怎么使用配置器

配置器是容器的内存管理工具,实际的内存分配、初始化、销毁、回收工作由他干。

C++的配置器继承自allocator类,这是个模板类可以自己设置内存元素大小,所以我们不用关心到底要分配多少字节。

代码

效果

a.allocate(num)

为num个元素分配内存

a.construct(p)

初始化指针p的指向元素

destroy(p)

销毁p所指的元素

deallocate(p,num)

回收从p开始的num个元素空间

 

下面我们来看看vector的一个内部初始化函数的实现代码:

template <class T, class Allocator>

vector<T,Allocator>::vector(size_type num, const T&val, const Allocator& a) :alloc(a)

{

sizeElems =numElems = num;//这两个是类变量

elems =alloc.allocate(num);//这个是类变量

 

for(size_type i= 0; i < num; ++i)

{

alloc.construct(&elems[i], val);//用val初始化

}

}

 

这个for循环效率不行,针对没有初始化的内存空间,所以C++提供了另外一些初始化函数:

代码

效果

uninitialize_fill(beg, end, val)

用val初始化beg-end

uninitialize_fill_n(beg, num, val)

用val初始化beg以及之后num个元素

uninitialize_copy(beg, end, mem)

把beg-end复制到mem开头的空间

 

其中uninitialized_fill_n的代码实现如下,其他原理相同。

template< class ForwardIt, class Size,class T >

void uninitialized_fill_n(ForwardIt beg,Size num

                          const T& value)

{

typedef typename std::iterator_traits<ForwardIt>::value_typeValue;

ForwardIt save(beg);

try{

   for (; num--; ++beg) {

       ::new (static_cast<void*>(&*beg)) Value(value);

}

}

catch(...)

{

for(; save!=beg; ++save)

{

save->~Value();

throw;

}

}

}

使用的是placementnew操作。加入了异常安全。

 

 

这样我的代码很漂亮了。

template <class T, class Allocator>

vector<T,Allocator>::vector(size_type num, const T&val, const Allocator& a) :alloc(a)

{

sizeElems =numElems = num;//这两个是类变量

elems =alloc.allocate(num);//这个是类变量

uninitialize_fill_n(elems,num, val);

}

 

然后是reserve的实现:

template <class T, class Allocator>

void vector<T,Allocator>::reserve(size_type size)

{

if (size <sizeElems)

return;

T* newElems =alloc.allocate(size);

unintialized_copy(elems,elems + numElems, newElem);//把原来的拷贝过来

 

for (size_type i= 0; i < numElems; ++i)

{

alloc.destroy(&elems[i]);

}

alloc.deallocate(elems,sizeElems);

sizeElems =size;

elems =newElems;

}

 

C++中提供了未初始化空间迭代器raw_storage_iterator,这样复制构造函数可以把上面的unintialized_copy,替换成更牛逼的代码:

template <class T, class Allocator>

vector<T, Allocator>::vector( constvector<T,>&val, const Allocator& a) : alloc(a)

{

sizeElems =numElems = val.size();//这两个是类变量

elems =alloc.allocate(numElems);//这个是类变量

......///主要是把原来的删除

copy(val.begin(),val.end(), raw_storage_iterator<T*, T>(elems));

}

 

(2)自定义配置器

现在关注一下怎么自定义配置器,下面是模板,以后照着改就行了。最关键的是怎么编写allocate(), deallocate()函数,这样可以实现内存优化分配。

template<class T>class allocator{

   public:

       typedef  T    value_type;

       typedef  T*    pointer;

       typedef  const T*    const_pointer;

       typedef  T&    reference;

       typedef  const T&    const_reference;

       typedef  size_t    size_type;

       typedef  ptrdiff_t    difference_type;

 

       template<class U>

       struct rebind

       {

           typedef allocator<U>other;

       };

 

allocator() throw(){}

 

template<class U>

allocator(const allocator<U>&) throw(){}

 

~allocator() throw(){}

 

       pointer allocate(size_typen,const void * hint=0)

       {

           return (pointer)(::operator new(num * sizeof(T)));//global new

       }

 

       void deallocate(pointer p,size_type n)

       {

          ::operator delete ((void*)p);//global delete

       }

 

       void construct(pointer p,const T& value)

       {

          new( (void*)p)  T(value);//placementnew operator

       }

 

       void destroy(pointer p){p->~T();}//

 

       pointer address(reference x){return (pointer)&x;}

 

       const_pointer const address(const_referencex)

       {

           return (const_pointer)&x;

       }

 

       size_type max_size() const{

           return size_type(numeric_limits<size_t>::max()/sizeof(T));

       }

};

}//end 

你可能感兴趣的:(《C++标准程序库》小结第十五章-自定义空间配置器)