C ++ standard STL-sgi stl source code learning notes (05) stl_vector and some issues refined 1C ++ standard STL-sgi stl source code

Source: Internet
Author: User

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.

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.