C ++ Standard Stl-sgi stl source code learning notes (06) stl_vector and some problem details 2 push_back Function Analysis

Source: Internet
Author: User

In the previous article, the story about stl_vector is just the beginning. In this article, we will analyze the details in vector.

 

Again, I have not read any books on stl source code analysis. I emphasize that this is to prevent others from misunderstanding that I copied it from other places.

The subsequent articles will detail the function implementation in vector.I try my best to make it small, and I can try my best to use my own language and my own analysis results to make it big.

The implementation process of the home presentation will not waste everyone's time. If you do not write well, please forgive me.

 

The push_back function is used to insert data from the position indicated by _ M_finish. If the pre-allocated storage unit is not enough, it will be extended and will be analyzed later.

This problem is explained.

Void push_back (const _ Tp & _ x) {if (_ M_finish! = _ M_end_of_storage) {construct (_ M_finish, _ x); ++ _ M_finish;} else _ M_insert_aux (end (), _ x );} // ** // * The implementation is the same as the above, except that the default initialization value is used wherever Initialization is required. // ** void push_back () {if (_ M_finish! = _ M_end_of_storage) {construct (_ M_finish); ++ _ M_finish;} else _ M_insert_aux (end ());}

1. What is the difference between _ M_finish and _ M_end_of_storage? _ M_finish and _ M_end_of_storage are also inherited by vectors from vector_base,

    However, the roles of the two are different.

[_ M_finish]: a pointer to the data type to execute the data for the current operation. During the default initialization, _ M_finish = _ M_start. That is, it points to the underlying storage element.

Array header elements. For example, if the push_back data is constantly pushed to the inside, _ M_finish will constantly move like the end of the array,

Until _ M_end_of_storage.

      

[_ M_end_of_storage]: _ M_end_of_storage when using vector to initialize and allocate the Array Memory for the first time, it is directed to the next position of the last element of the array.

Because during initialization_ M_finish = _ M_start, _ M_end_of_storage = _ M_start + _ n. (_ n indicates the number of elements ).

With the constant operations on the vector, the _ M_end_of_storage may change later.

 

To put it bluntly, _ M_finish is the cursor swimming between _ M_start (header pointer) and _ M_end_of_storage (the last position of the tail pointer.

 

2. When executing the push_back (n) operation, the system first checks whether the size of the array has reached the upper limit. If _ M_finish = _ M_end_of_storage.

The storage unit is expanded in _ M_insert_aux (end (), _ x.

 

3. If the upper limit is not reached, that is to say, if there is no space available, assign a value to the position pointed to by the current cursor _ M_finish and move the cursor to the next position.

   

4. If the upper limit is not reached, use construct to assign a value to the memory area pointed to by _ M_finish. 

template <class _T1, class _T2>inline void _Construct(_T1* __p, const _T2& __value) {  new ((void*) __p) _T1(__value);}

  This usage of new is not very common, but it is explained in the "special tools and technology" section after <c ++ primer>.

new (place_address) typenew (place_address) type(parm-list)

 5. If the upper limit is reached, the storage area needs to be expanded, which is twice the size of the original area.    

Const size_type _ old_size = size (); // obtain the length of the original storage region const size_type _ len = _ old_size! = 0? 2 * _ old_size: 1; // expansion is twice the original iterator _ new_start = _ M_allocate (_ len ); // reapply for memory iterator _ new_finish = _ new_start according to the new storage length; _ STL_TRY {_ new_finish = uninitialized_copy (_ M_start, _ position, _ new_start ); // copy the data in the original array between _ M_start-> _ M_finish to the new storage area construct (_ new_finish, _ x); // insert new value. // Insert new data, which is the same as the previous operation + _ new_finish; // go next. // move _ M_finish _ new_finish = uninitialized_copy (_ position, _ M_finish, _ new_finish);} _ STL_UNWIND (destroy (_ new_start ,__ new_finish ), _ M_deallocate (_ new_start ,__ len); destroy (begin (), end (); _ M_deallocate (_ M_start, _ M_end_of_storage-_ M_start ); // release the original storage memory _ M_start = _ new_start; // handle other changes _ M_finish = _ new_finish; _ M_end_of_storage = _ new_start + _ len;

  Some people may not understand why they need to call the uninitialized_copy function twice. In fact, they think too much, depending on the above call:

_ M_insert_aux (end (), _ x). The end () function is used to obtain _ M_finish. In the uninitialized_copy function, the system first checks the result.   

template <class _InputIter, class _ForwardIter>_ForwardIter __uninitialized_copy_aux(_InputIter __first, _InputIter __last,                         _ForwardIter __result,                         __false_type){  _ForwardIter __cur = __result;  __STL_TRY {    for ( ; __first != __last; ++__first, ++__cur)      _Construct(&*__cur, *__first);    return __cur;  }  __STL_UNWIND(_Destroy(__result, __cur));}

   Although many layers of conversions are passed, we can still see the _ first! = _ Last. Therefore, this statement will not be executed in the preceding call. Does this seem a bit redundant?

No. Because _ M_insert_aux provides a general usage method, a general implementation is required. The above call will eventually get _ new_finish = _ new_finish.

So there is no need to tangle.

  

Finally, the versions of another push_back parameter do not need to be explained much, because the above method and principle are the same in implementation between the two, which is useless.

    

    

 

 

 

 

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.