C ++ Primer study note _ 47_STL Analysis (2): vector source code analysis, memory distributor Allocator

Source: Internet
Author: User

C ++ Primer study note _ 47_STL Analysis (2): vector source code analysis, memory distributor Allocator
1. Source Code of vector initialization: Track A simple program, observe the initialization process of vector, and debug the single-step execution.

#include 
 
  #include 
  
   using namespace std;int main(){    vector
   
     v;    return 0;}
   
  
 
1. First, the code is executed.
vector() _NOEXCEPT        : _Mybase()        {    // construct empty vector        }    explicit vector(const _Alloc& _Al) _NOEXCEPT        : _Mybase(_Al)        {    // construct empty vector, allocator        }
2. Execute allocator
    allocator() _THROW0()        {    // construct default allocator (do nothing)        }
3. Further execution
    _Vector_alloc(const _Alloc& _Al = _Alloc())        : _Mypair(_One_then_variadic_args_t(), _Al)        {    // construct allocator from _Al        _Alloc_proxy();        }
4. allocate memory. The Initialization is 0. After a series of calls, the initialization is complete.
    _Vector_val()        {    // initialize values        _Myfirst = pointer();        _Mylast = pointer();        _Myend = pointer();        }    pointer _Myfirst;    // pointer to beginning of array    pointer _Mylast;    // pointer to current end of sequence    pointer _Myend;    // pointer to end of array    };
Ii. capacity

1. First, the implementation of vector in VC 2008 is complicated, although the Declaration of vector is consistent with that of VC6.0, as follows:

Template <class _ Ty, class _ Ax = allocator <_ Ty> // The second parameter is the class vector with the default parameter;

2. However, in VC2008, vector also has a base class, as shown below:

// TEMPLATE CLASS vectortemplate < class _Ty,         class _Ax >class vector    : public _Vector_val<_Ty, _Ax>{};

3. Let's take a look at the base class _ Vector_val:

// TEMPLATE CLASS _Vector_valtemplate < class _Ty,         class _Alloc >class _Vector_val    : public _CONTAINER_BASE_AUX_ALLOC<_Alloc>{    // base class for vector to hold allocator _Alvalprotected:    _Vector_val(_Alloc _Al = _Alloc())        : _CONTAINER_BASE_AUX_ALLOC<_Alloc>(_Al), _Alval(_Al)    {        // construct allocator from _Al    }    typedef typename _Alloc::template    rebind<_Ty>::other _Alty;    _Alty _Alval;   // allocator object for values};

 


4. To understand the type of _ Alty, you have to take a look at the allocator template class:

 

template
 
   class allocator{    template<> class _CRTIMP2_PURE allocator
  
       {        // generic allocator for type void    public:        template
   
            struct rebind        {            // convert an allocator
    
      to an allocator <_Other>            typedef allocator<_Other> other;        };        ....    };    ...};
    
   
  
 

Typedeftypename_Alloc: templaterebind <_ Ty>: other_Alty; The type definition is used as a whole. Suppose we use vector now. , Then _ Ty is int, _ Ax is allocator When the vector class is passed to the base class Vector_val, _ Alloc is allocator. ; You can see allocator Is the feature of allocator template class, rebind <_ Ty> is the member template class, other is the custom type of the member template class, And _ Ty is the int type, then the other type is also allocator That is, _ Alty is of the type allocator. . _ Alty _ Alval; that is, the base class defines a allocator Type Member, which is inherited by vector and used to allocate memory for elements in the vector.

For example, iteratornew_data = alloc. allocate (new_size); note that the standard vector: iterator is implemented by the template class. The following implementation simply treats it as a pointer, in fact, the real implementation of the iterator class is that there is a pointer member inside, pointing to the container element.

××××××××××××××××××××××××××××××××××××××××××× ××××××××××××××××××××××××××××××××××××××××××× *

Compared with the implementation of list, it inherits a member of its base class _ List_nod allocator <_ Node> _ Alnod; as follows:

Typename _ Alloc: template rebind <_ Node>: other _ Alnod; // allocator object for nodes

Among them, _ Node has three members:

_ Nodeptr _ Next; // successor node, or first element if head

_ Nodeptr _ Prev; // predecessor node, or last element if head

_ Ty _ Myval; // the stored value, unused if head

For list , Then _ Ty is the int type. When creating a new node, the two-way linked list is implemented as follows:

_ Nodeptr _ Pnode = this-> _ Alnod. allocate (1); // allocates the space of a node and returns a pointer to the node.

In fact, list also inherits two members of the other two base classes, as follows:

Typename _ Alloc: template rebind <_ Nodeptr>: other _ Alptr; // allocator object for pointers to nodes

Typename _ Alloc: template rebind <_ Ty>: other _ Alty _ Alval; // allocator object for values stored in nodes

××××××××××××××××××××××××××××××××××××××××××× ××××××××××××××××××××××××××××××××××××××××××× *

3. How to Implement continuous space in a vector Dynamic Array

1. Track A simple program, observe the capacity allocation process of the vector, and debug the single-step execution.

#include 
 
  #include 
  
   using namespace std;int main(){    vector
   
     v;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    v.push_back(1);    cout << v.capacity() << endl;    return 0;}
   
  
 
 

Capacity is calculated as follows: capacity increases to the original capacity + the original capacity/2;

The increasing source code tracking results are as follows:

    size_type _Grow_to(size_type _Count) const        {    // grow by 50% or at least to _Count        size_type _Capacity = capacity();        _Capacity = max_size() - _Capacity / 2 < _Capacity            ? 0 : _Capacity + _Capacity / 2;    // try to grow by 50%        if (_Capacity < _Count)            _Capacity = _Count;        return (_Capacity);        }

2. The concept of capacity and vector size is different. capacity> = size, as shown in:

Size refers to the interval of _ Mylast-_ Myfirst; capacity refers to the interval of _ Myend-_ Myfirst; that is, there is no space available.

When push_back is usually followed by multiple copy and destructor operations, a large size () space capacity can be split at once to reduce the efficiency problems caused by frequent operations.

Generally, the vector caches a portion of the memory space to accommodate more elements. In this way, when a new element is inserted, the memory does not need to be re-allocated, improving the insertion speed.

Iv. Memory distributor Allocator

Allocator template class:

#include 
 
  template 
  
    class allocator{public:    T *allocate(size_t);    void deallocate(T *, size_t);    void construct(T *, size_t);    void destroy(T *);    //.......};
  
 

Of course, the actual interface is not that simple to implement, but the functions are roughly the same:

Allocate calls operator new; deallocate calls operator delete; construct calls placement new (that is, the copy constructor is called on the allocated memory), and destroy calls the destructor.

Refer:

C ++ primer version 4
Valid tive C ++ 3rd
C ++ programming specifications


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.