Part 1ArticleStl_deque's design philosophy and STL memory management are explained in a rough way. At least we can see the tip of the iceberg.
In this article, I will refine the analysis of vector and analyze some functions in detail. In some cases, it is better to clarify some problems.
Open the source code of stl_vector and find that the design idea of the vector is exactly the same as that of stl_deque. It is reasonable to think about it and maintain the consistency of implementation, but stl_vector does not provide a definite
The template class iterator implements the iterator, but implements the iteration In the Vector Template Class, but there is basically no big difference with deque. Let's take a look at the source code:
1. I will not explain the design part this time. I will explain the implementation part. if I didn't read the previous article, I tried my best to make it irrelevant to the previous article, but I 'd better understand the design part. details
Refer to this article: C ++ standard STL -- sgi stl source code learning notes (04) stl_deque & STL memory management.
2. the memory management template class of vector: _ vector_alloc_base. It is a template class, but there is a special version. The difference lies in the Allocator (I do not know the name of this distributor)
Is it appropriate? When I used to read the Apache source code analysis, allocator is called a sub-allocation, but the roles and concepts of the two are different.) is the object a member variable.
Well, for the generic _ vector_alloc_base template class and the special _ vector_alloc_base template class, we will distinguish from the memory operation method above:
General _ vector_alloc_base template memory operation method:
_ TP * _ m_allocate (size_t _ n) // use a member variable to perform memory operations {return _ m_data_allocator.allocate (_ n );} void _ m_deallocate (_ TP * _ p, size_t _ n) {If (_ p) _ m_data_allocator.deallocate (_ p, _ n );}
Special _ vector_alloc_base memory operation method:
Typedef typename _ alloc_traits <_ TP, _ Allocator>: _ alloc_type; // No member Variable _ TP * _ m_allocate (size_t _ n) is used directly) {return _ alloc_type: allocate (_ n);} void _ m_deallocate (_ TP * _ p, size_t _ n) {_ alloc_type :: deallocate (_ p, _ n );}
Of course, both common and special templates use the traits technology.
3. Vector member variables:
_ TP * _ m_start; // start _ TP * _ m_finish; // during initialization, _ m_finish = _ m_start _ TP * _ m_end_of_storage // points to the next position of the last element. note that it is not the last element.
These three member variables are all vector inherited from the base class. These three pointers point to three different positions. You can see from the constructor:
_ Vector_base (size_t _ n, const _ alloc &): _ m_start (0), _ m_finish (0), _ m_end_of_storage (0) {_ m_start = _ m_allocate (_ n); _ m_finish = _ m_start; _ m_end_of_storage = _ m_start + _ n ;}
Initialize _ m_start, _ m_finish, _ m_end_of_storage according to the initialization length _ n.
Explicit vector (const allocator_type & _ A = allocator_type (): _ base (_ A) {} vector (size_type _ n, const _ TP & _ value, const allocator_type & _ A = allocator_type (): _ base (_ n, _ A) {_ m_finish = uninitialized_fill_n (_ m_start, _ n, _ value);} explicit vector (size_type _ n): _ base (_ n, allocator_type () {_ m_finish = uninitialized_fill_n (_ m_start, _ n, _ TP ();} vector (const vector <_ TP, _ alloc> & _ x): _ base (_ x. size (), _ x. get_allocator () {_ m_finish = uninitialized_copy (_ x. begin (), _ x. end (), _ m_start );}
We can see from the constructor provided by vector that the base class _ vector_base is used for initialization. Because the Vector Template Class provides a default parameter, you can use the default
Allocator.
Inline T * allocate (ptrdiff_t size, T *) {set_new_handler (0); T * TMP = (T *) (: Operator new (size_t) (size * sizeof (t); If (TMP = 0) {cerr <"out of memory" <Endl; exit (1 );} return TMP ;}
After initialization, m_start gets the return pointer of the allocate function, while m_finish is initialized by default, which is the same as m_start. See the processing of _ m_finish.
The macro uninitialized_fill_n processes and redirects to _ uninitialized_fill_n, and then to _ uninitialized_fill_n_aux.
Sgi stl has made quite complicated processing here, mainly to judge the element type judgment in the vector, whether it is the pod type or not the pod type. (pod? Plain old data, simple old data, built-in type is pod
<C ++ required?> clause 11 puts things in the class during compilation. I talked about the V-table in the class polymorphism and thought about whether to write an essay .)
Template <class _ forwarditer, class _ size, class _ TP, class _ TP1> inline _ forwarditer _ uninitialized_fill_n (_ forwarditer _ first, _ SIZE _ n, const _ TP & _ x, _ TP1 *) {typedef typename _ type_traits <_ TP1 >:: is_pod_type _ is_pod; return _ uninitialized_fill_n_aux (_ first, _ n, _ x, _ is_pod ());}
The _ type_traits template class provides many special features to handle this build-in type. For build-in pod is_pod_type, all are _ true_type.
Template <class _ forwarditer, class _ size, class _ TP> inline _ forwarditer _ uninitialized_fill_n_aux (_ forwarditer _ first, _ SIZE _ n, const _ TP & _ x, _ true_type) {return fill_n (_ first, _ n, _ x);} template <class _ forwarditer, class _ size, class _ TP> _ forwarditer _ uninitialized_fill_n_aux (_ forwarditer _ first, _ SIZE _ n, const _ TP & _ x, _ false_type) {_ forwarditer _ cur = _ first; _ stl_try {for (; _ n> 0; -- _ n, ++ _ cur) _ construct (& * _ cur, _ x); Return _ cur;} _ stl_unwind (_ destroy (_ first, _ cur ));}
Here is the final implementation of _ m_finish. Add the source code of fill_n:
Template <class _ outputiter, class _ size, class _ TP> _ outputiter fill_n (_ outputiter _ first, _ SIZE _ n, const _ TP & _ value) {_ stl_requires (_ outputiter, _ outputiterator); For (; _ n> 0; -- _ n, ++ _ First) * _ first = _ value; return _ first ;}
Whether the element type in the vector is pod or not, it moves _ m_start and Initialization is also performed.