Allocator and stlallocator for stl Analysis

Source: Internet
Author: User

Allocator and stlallocator for stl Analysis

Allocator encapsulates the memory management system of the stl standard library. The string, container, algorithm, and some iostreams of the standard library are allocated and released through allocator. The component of the standard library has a allocator class specified by the parameter. For example, the prototype of vector is:

template<typename _Tp, typename _Alloc = std::allocator<_Tp> >class vector : protected _Vector_base<_Tp, _Alloc>

The second parameter _ Alloc specifies the allocator used. The default value is std: allocator. You can also specify allocator.

vector<int, __gnu_cxx::malloc_allocator<int> > malloc_vector;

Malloc_allocator will be used to allocate and release the memory.
GNU gcc implements a variety of allocator. The following describes the functions of allocator. My g ++ version is 4.8.
1. new_allocator
This is the default allocator used by g ++ 4.8, that is, the allocator used by std: allocator.
Std: allocator: is defined in/usr/include/c ++/4.8/bits/allocator. h:

template<typename _Tp>class allocator: public __allocator_base<_Tp>

Std: The interface used by allocator is defined by _ allocator_base, while the latter is in/usr/include/i386-linux-gnu/c ++/4.8/bits/c ++ allocator. h is defined as new_allocator:

# define __allocator_base  __gnu_cxx::new_allocator

New_allocator is simply packaged: operator new and operator delete, implemented in/usr/include/c ++/4.8/ext/new_allocator.h

pointer allocate(size_type __n, const void* = 0) { if (__n > this->max_size())     std::__throw_bad_alloc();   return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); } void  deallocate(pointer __p, size_type) { ::operator delete(__p); }

There is no memory pool, so if there is still a program that uses stl and memory is not recycled, it must be because the libc cache is not released, not the reason for stl.

2. malloc_allocator
Malloc_allocator directly packs malloc and free, which are defined in the/usr/include/c ++/4.8/ext/malloc_allocator.h header file,

pointer  allocate(size_type __n, const void* = 0) { if (__n > this->max_size())     std::__throw_bad_alloc();   pointer __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp)));   if (!__ret)     std::__throw_bad_alloc();   return __ret; } void  deallocate(pointer __p, size_type) { std::free(static_cast<void*>(__p)); }

3. array_allocator
Array_allocator does not call new or malloc to apply for memory allocation from the operating system, but directly uses the allocated memory. The allocator can be used to reuse memory, which is highly efficient.

array_allocator(array_type* __array = 0) _GLIBCXX_USE_NOEXCEPT       : _M_array(__array), _M_used(size_type()) { }        Pointer allocate(size_type __n, const void* = 0) {   if (_M_array == 0 || _M_used + __n > _M_array->size())     std::__throw_bad_alloc();   pointer __ret = _M_array->begin() + _M_used;   _M_used += __n;   return __ret,_M_used}

_ M_array points to the allocated memory block address, and _ M_used points to the idle address displacement. The initial value is 0. After each memory segment is allocated, _ M_used is moved back. when the required memory volume exceeds the idle memory size, the bad_alloc exception is thrown.

4. debug_allocator
You can package any other allocator, including G ++'s built-in or user-defined allocator. When allocating memory, an additional memory size is allocated for storing the applied memory, when released, check whether the released memory size is the same as the saved value. If the size is different, an exception is thrown. The specific application release action is executed by the encapsulated allocator.

pointer allocate(size_type __n) {   pointer __res = _M_allocator.allocate(__n + _M_extra);        size_type* __ps = reinterpret_cast<size_type*>(__res);   *__ps = __n;   return __res + _M_extra; } void deallocate(pointer __p, size_type __n) {   if (__p)   {     pointer __real_p = __p - _M_extra;     if (*reinterpret_cast<size_type*>(__real_p) != __n)     {       throw std::runtime_error("debug_allocator::deallocate wrong size");     }     _M_allocator.deallocate(__real_p, __n + _M_extra);   }   else     throw std::runtime_error("debug_allocator::deallocate null pointer"); }

_ Ps stores the length of the memory currently allocated. When deallocate is used, it checks whether the size of the released memory is equal to this value. Debug_allocator can detect memory leakage at the cost of allocating more space for debugging.

5. _ pool_alloc
The only allocator with a memory pool is also the allocator used by G ++ by default in the early stage. The second chapter of Hou Jie's stl source code analysis analyzes its code implementation in detail. the principle is to reduce memory fragments. operator new is called directly when the memory allocated is greater than bytes, while the memory smaller than bytes is retrieved from a free list, the memory in the free list can be reused and will not be returned to the operating system during the program running. The process is complicated. If you are interested, refer to stl source code analysis.


Reference:
Https://gcc.gnu.org/onlinedocs/gcc-4.9.1/libstdc++/manual/manual/memory.html#std.util.memory.allocato


Vector <string, allocator> error allocator undefined identifier

You do not need to define allocator yourself during instantiation. If you want to write allocator by yourself
1: No. 2. It is complicated for new users.

So you can simply use the default one. The default allocator is a template that will automatically replace it with allocator <string>, so you don't need to worry about it.

You can use the string vector: std: vector <std: string>.

Clause 10: Pay attention to the agreements and constraints of distributors
The splitter is weird. They were initially developed for the abstract memory model, allowing database developers to ignore the differences between near and far pointers (that is, DOS and its harmful products) on some 16-bit operating systems ), but failed. The splitter is also designed to promote the development of the full-featured memory manager, but it turns out that method may cause Efficiency Loss in some parts of STL. In order to avoid efficiency impact, the C ++ Standards Committee added words to the standards, weakened the distributors as objects, and expressed their hopes that they would not lose operation capabilities.

There are more. Just like operator new and operator new [], STL splitters are responsible for allocating (and reclaiming) original memory, but the customer interfaces of the splitters are almost identical to operator new, operator new [], and even malloc. Finally (and possibly astonishing), most standard containers never ask for memory from their related distributors. Never. The result distributor is. Well, the distributor is weird.

Of course, that's not their fault, and in any case, it doesn't mean they are useless. However, before I explain where the distributors are (that is the subject of clause 11), I need to explain where they are. There are a lot of things that the distributor can do, but it cannot, and before you try to start using it, it is important to know the boundaries of the domain. If you don't, you will be hurt. In addition, the fact about the distributor is so unique that summing up its behavior is both enlightening and interesting. At least I want.

The list of constraints of a distributor starts with the residual typedef used for pointers and references. As I mentioned, a distributor was initially conceived as an abstract memory model in which case it makes sense to provide pointers and referenced typedef in the memory model they define. In the C ++ standard, the default distributor (cleverly called allocator <T>) of type T objects provides typedef allocator <T >:: pointer and allocator <T> :: you also want the User-Defined distributor to provide these typedef.

The C ++ veteran immediately discovered this problem because there was no way to fabricate references in C ++. This requires the ability to overload operator. ("point operator"), which is not allowed. In addition, an example of using a proxy object is used to create an object referenced by a behavior image, which may cause many problems. (Such a problem arises in Clause 18. A comprehensive discussion of proxy objects is directed to Clause 30 of "More Effective C ++". You can know when they will not work .)

As far as the splitters in STL are concerned, the technical disadvantage of no proxy object will lead to invalid pointers and references of typedef, in fact, the standard explicitly allows the library to implement the assumption that the pointer typedef of each distributor is a synonym of T *, and the reference typedef of each distributor is the same as T. Yes, the library implementation can ignore typedef and directly use the original pointer and reference! So even if you can try to write a method that successfully provides a new pointer and a quote type distributor, you can't go anywhere, because the STL implementation you use will freely ignore your typedef. Very elegant, isn't it?

When you admire standardization, I will introduce it again. The allocator is an object, which indicates that they may have member functions, embedded types and typedef (such as pointer and reference, but the standard allows STL implementation to think that all the same types of distributor objects are equivalent and always equal in comparison. Very abrupt, it sounds not terrible, and of course there are good motives for it ...... The Rest Of The full text>

What is template <class T, class Allocator = allocator <T>?

C ++ template declaration

You can see that this is the code of the STL container (vector, list ).

This template contains two template parameters: T and Allocator. Allocator has a default value. The default value is allocator. <T>

Allocator is also a template and requires a parameter. You can refer to its definition. allocator <T> is an instance of the template allocator.

To understand STL, you must have some knowledge about the Template. We recommend that you read C ++ Template.
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.