STL source code analysis container stl_vector.h

Source: Internet
Author: User

This article is senlie original, reproduced Please retain this address: http://blog.csdn.net/zhengsenlie


Vector
----------------------------------------------------------------------


Description:
1. iterator
Vector maintains a continuous linear space, and its iterator is a common pointer,
All the necessary conditions for randomaccessiterator: Operator *, operator->, operator ++, operator --, operator +,
Operator-, operator + =, operator-=, operator []
2. Data Structure
The data structure used by vector is linear continuous space.
The iterator start and finish indicate the currently used range in the configured continuous space.
The iterator end_of_storage points to the end of the entire continuous space.


When a new element is added, if the current capacity is used, the capacity will be doubled.
If twice the capacity is still insufficient, it will be expanded to a large enough capacity.
Capacity Expansion Process: reconfiguration, element movement, and release of original space
The so-called dynamic increase is not followed by a new space after the original space, because the original space cannot be guaranteed
There is still space for configuration. Therefore, if any operation on the vector causes space reconfiguration,
All iterators pointing to the original vector become invalid.
Figure 4-2


Example:

vector<int> V;V.insert(V.begin(), 3);assert(V.size() == 1 && V.capacity() >= 1 && V[0] == 3);

Source code:
# Ifndef _ sgi_stl_internal_vector_h # DEFINE _ sgi_stl_internal_vector_h1_stl_begin_namespace # If defined (_ SGI )&&! Defined (_ gnuc _) & (_ mips_sim! = _ Mips_sim_abi32) # pragma set woff 1174 # endiftemplate <class T, class alloc = alloc> class vector {public: typedef t value_type; typedef value_type * pointer; typedef const value_type * const_pointer; typedef value_type * iterator; // The vector iterator is a native pointer typedef const value_type * struct; typedef value_type & reference; typedef const value_type & const_reference; typedef size_t size_type; typedef PT Rdiff_t difference_type; # ifdef _ effectypedef extends <const_iterator> extends; typedef extends <iterator> extends; # else/* _ splits */typedef extends <const_iterator, value_type, const_reference, difference_type> const_reverse_iterator; typedef reverse_iterator <iterator, value_type, reference, d Ifference_type> reverse_iterator; # endif/* _ stl_class_partial_specialization */protected: typedef simple_alloc <value_type, alloc> data_allocator; // continuous space? Iterator start; // indicates the iterator finish of the currently used space header; // indicates the end of the currently used space iterator end_of_storage; // indicates the end of the currently available space void insert_aux (iterator position, const T & X); void deallocate () {If (start) data_allocator: deallocate (START, end_of_storage-Start);} // fill and initialize void fill_initialize (size_type N, const T & Value) {start = allocate_and_fill (n, value); finish = start + N; end_of_storage = finish;} public: iterator Begin () {return start;} const_iterator begin () const {return start;} iterator end () {return finish;} const_iterator end () const {return finish ;} reverse_iterator rbegin () {return reverse_iterator (end ();} reverse rbegin () const {return const_reverse_iterator (end ();} reverse_iterator rend () {return reverse_iterator (begin ();} const_reverse_iterator rend () const {retu Rn const_reverse_iterator (begin ();} size_type size () const {return size_type (end ()-begin ();} size_type max_size () const {return size_type (-1) /sizeof (t);} size_type capacity () const {return size_type (end_of_storage-begin ();} bool empty () const {return begin () = end ();} reference operator [] (size_type N) {return * (begin () + n);} const_reference operator [] (size_type N) const {RET Urn * (begin () + n);} vector (): Start (0), finish (0), end_of_storage (0) {}// constructor, specify the vector size N and Initial Value vector (size_type N, const T & Value) {fill_initialize (n, value) ;}vector (int n, const T & value) {fill_initialize (n, value);} vector (long N, const T & Value) {fill_initialize (n, value);} explicit vector (size_type N) {fill_initialize (n, T ();} vector (const vector <t, alloc> & X) {start = Allocate_and_copy (X. end ()-X. begin (), X. begin (), X. end (); finish = start + (X. end ()-X. begin (); end_of_storage = finish;} # ifdef _ stl_member_templates template <class inputiterator> vector (inputiterator first, inputiterator last): Start (0), finish (0 ), end_of_storage (0) {range_initialize (first, last, iterator_category (first);} # else/* _ stl_member_templates */vector (const_iterator first, Const_iterator last) {size_type n = 0; distance (first, last, n); Start = allocate_and_copy (n, first, last); finish = start + N; end_of_storage = finish ;} # endif/* _ stl_member_templates */~ Vector () {destroy (START, finish); deallocate () ;}vector <t, alloc> & operator = (const vector <t, alloc> & X ); void reserve (size_type N) {If (capacity () <n) {const size_type old_size = size (); iterator TMP = allocate_and_copy (n, start, finish); destroy (start, finish); deallocate (); Start = TMP; finish = TMP + old_size; end_of_storage = start + N ;}} reference Front () {return * begin ();} const_refe Rence Front () const {return * begin ();} reference back () {return * (end ()-1);} const_reference back () const {return * (end ()-1);} // void push_back (const T & X) {If (finish! = End_of_storage) {// check whether there is any backup space construct (finish, x); // Yes, directly construct the element ++ finish in the backup space; // adjust iterator finish} else insert_aux (end (), x); // No, Extended Space (reconfiguration, element movement, and release of original space )} void swap (vector <t, alloc> & X) {_ STD: swap (START, X. start); _ STD: swap (finish, X. finish); _ STD: swap (end_of_storage, X. end_of_storage);} iterator insert (iterator position, const T & X) {size_type n = position-begin (); If (finish! = End_of_storage & position = end () {construct (finish, x); ++ finish;} else insert_aux (Position, x); Return begin () + N ;} iterator insert (iterator position) {return insert (Position, T () ;}# ifdef _ stl_member_templates template <class inputiterator> void insert (iterator position, inputiterator first, inputiterator last) {range_insert (position, first, last, iterator_category (first);} # else/ * _ Stl_member_templates */void insert (iterator position, const_iterator first, const_iterator last); # endif/* _ blank */void insert (iterator POs, size_type N, const T & X); void insert (iterator POs, int N, const T & X) {insert (Pos, (size_type) n, x);} void insert (iterator POs, long N, const T & X) {insert (Pos, (size_type) n, x);} void pop_back () {-- finish; // mark the tail end to one cell, indicates that End Element destroy (finish); // destructor End Element} // clear the iterator erase (iterator position) {If (Position + 1! = End () Copy (Position + 1, finish, position); -- finish; destroy (finish); Return position ;}// clear [first, last) iterator erase (iterator first, iterator last) {iterator I = copy (last, finish, first); [last, finish) copy the indicated element to destroy (I, finish) at the beginning of the first iterator; finish = finish-(last-first) the element in the [I, finish ); adjust the last-first position indicated by finish to return first;} void resize (size_type new _ Size, const T & X) {If (new_size <size () Erase (begin () + new_size, end (); else insert (end (), new_size-size (), x);} void resize (size_type new_size) {resize (new_size, T ();} // call erase to clear all elements void clear () {erase (begin (), end ();} protected: // configure and then fill in iterator allocate_and_fill (size_type N, const T & X) {iterator result = data_allocator :: allocate (n); // configure n Element Spaces _ stl_try {uninitialized_fi Ll_n (result, n, x); // global function. Based on the Type Characteristics of the result, it is decided to use the algorithm fill_n () or call construct () repeatedly to return the result;} _ stl_unwind (data_allocator: deallocate (result, n) ;}# ifdef _ partition template <class forwarditerator> iterator allocate_and_copy (size_type N, forwarditerator first, forwarditerator last) {iterator result = data_allocator: allocate (N ); _ stl_try {uninitialized_copy (first, last, result); Return resu Lt;} _ stl_unwind (data_allocator: deallocate (result, n);} # else/* _ partition */iterator allocate_and_copy (size_type N, const_iterator first, last) {iterator result = data_allocator: allocate (n); _ stl_try {uninitialized_copy (first, last, result); return result;} _ stl_unwind (data_allocator: deallocate (result, n) ;}# endif/* _ stl_member_templates */# ifdef _ stl_m Ember_templates template <class inputiterator> void range_initialize (inputiterator first, inputiterator last, input_iterator_tag) {for (; first! = Last; ++ first) push_back (* First);} // This function is only called by the constructor. we have to worry // about resource leaks, but not about maintaining invariants. template <class forwarditerator> void range_initialize (forwarditerator first, forwarditerator last, role) {size_type n = 0; distance (first, last, n); Start = allocate_and_copy (n, first, first, last); finish = start + N; e Topology = finish;} template <class inputiterator> void range_insert (iterator POs, inputiterator first, inputiterator last, iterator); Template <class forwarditerator> void range_insert (iterator POs, forwarditerator first, forwarditerator last, forward_iterator_tag); # endif/* _ stl_member_templates */}; Template <class T, class alloc> inline bool operator = (const vector <t, alloc> & X, Const vector <t, alloc> & Y) {return X. size () = y. size () & Equal (X. begin (), X. end (), Y. begin ();} template <class T, class alloc> inline bool operator <(const vector <t, alloc> & X, const vector <t, alloc> & Y) {return lexicographical_compare (X. begin (), X. end (), Y. begin (), Y. end () ;}# ifdef _ stl_function_tmpl_partial_ordertemplate <class T, class alloc> inline void swap (vector <t, alloc> & X, vector <t, Lloc> & Y) {X. swap (y) ;}# endif/* _ stl_function_tmpl_partial_order */template <class T, class alloc> vector <t, alloc> & Vector <t, alloc> :: operator = (const vector <t, alloc> & X) {If (& X! = This) {If (X. size ()> capacity () {iterator TMP = allocate_and_copy (X. end ()-X. begin (), X. begin (), X. end (); destroy (START, finish); deallocate (); Start = TMP; end_of_storage = start + (X. end ()-X. begin ();} else if (SIZE ()> = x. size () {iterator I = copy (X. begin (), X. end (), begin (); destroy (I, finish);} else {copy (X. begin (), X. begin () + size (), start); uninitialized_copy (X. begin () + siz E (), X. end (), finish);} finish = start + X. size () ;}return * This ;}template <class T, class alloc> void vector <t, alloc >:: insert_aux (iterator position, const T & X) {If (finish! = End_of_storage) {// will insert_aux be called to insert elements if there is not enough spare space? Why is there "finish! = End_of_storage? // --> In addition to push_back, insert_aux is called when there is not enough space. Normal insert is also implemented by insert_aux. // Why not copy_backward (Position, finish-1, finish) directly, and then * position = x_copy? Construct (finish, * (finish-1); ++ finish; t x_copy = x; copy_backward (Position, finish-2, finish-1); * position = x_copy ;} else {// No standby space position = finish const size_type old_size = size (); const size_type Len = old_size! = 0? 2 * old_size: 1; // if the original size is 0, configure the space of one element. Otherwise, configure the original space iterator new_start = data_allocator :: allocate (LEN); // The actual configuration of iterator new_finish = new_start; _ stl_try {// copy all the content of the original space to the new space positition new_finish = uninitialized_copy (START, position, new_start); // set the initial value x construct (new_finish, x) for the new element; // adjust the iterator finish ++ new_finish ;//?? I think the following line of code is useless. Because there is no spare space, position = finish new_finish = uninitialized_copy (Position, finish, new_finish) ;}# ifdef _ stl_use_exceptions catch (...) {// an exception occurs when three dots are used ...?? // Roll back destroy (new_start, new_finish); data_allocator: deallocate (new_start, Len); throw ;} # endif/* _ stl_use_exceptions * // destroy (begin (), end (); deallocate (); // adjust the iterator, point to the new vector start = new_start; finish = new_finish; end_of_storage = new_start + Len;} template <class T, class alloc> // insert n elements starting from position, element Initial Value: xvoid vector <t, alloc >:: insert (iterator position, size_type N, const T & X) {If (n! = 0) {// when n! If (size_type (end_of_storage-finish)> = N) {// The backup space is greater than the number of new elements t x_copy = x; const size_type elems_after = finish-position; // number of existing elements after the insertion point iterator old_finish = finish; If (elems_after> N) {// "number of existing elements after the insertion point" greater than "Number of new elements" // uninitialized_copy is used when the space is not initialized, and copy_backwarduninitialized_copy (finish-N, finish, finish); finish + = N; copy_backward (Position, old_finish-N, old_finish ); Fill (Position, Position + N, x_copy ); // enter a new value from the insertion point} else {// "number of existing elements after the insertion point" less than "Number of new elements" uninitialized_fill_n (finish, N-elems_after, x_copy ); finish + = N-elems_after; uninitialized_copy (Position, old_finish, finish); finish + = elems_after; fill (Position, old_finish, x_copy );}} else {// The standby space is smaller than the number of new elements. Const size_type old_size = size (); // first, the new length is determined: twice the old length or the old Length + the number of new elements, the two parameters take the maximum value const size_type Len = Old_size + max (old_size, n); iterator new_start = data_allocator: allocate (LEN); iterator new_finish = new_start; _ stl_try {// use uninitialized_copy to copy the element before the insertion point of the old vector to the new space new_finish = uninitialized_copy (START, position, new_start ); // use uninitialized_fill_n to add new elements to the new space new_finish = uninitialized_fill_n (new_finish, n, x); // use uninitialized_copy to copy the elements after the inserted points of the old vector to the new space new_finish Ized_copy (Position, finish, new_finish) ;}# ifdef _ stl_use_exceptions catch (...) {destroy (new_start, new_finish); data_allocator: deallocate (new_start, Len); throw ;} # endif/* _ stl_use_exceptions * // clear and release the old vector destroy (START, finish); deallocate (); // adjust the flag start = new_start; finish = new_finish; end_of_storage = new_start + Len ;}}# ifdef _ stl_member_templatestemplate <class T, class all OC> template <class inputiterator> void vector <t, alloc>: range_insert (iterator POs, inputiterator first, inputiterator last, input_iterator_tag) {for (; first! = Last; ++ first) {pos = insert (Pos, * First); ++ POS ;}} template <class t, class alloc> template <class forwarditerator> void vector <t, alloc>: range_insert (iterator position, forwarditerator first, forwarditerator last, forward_iterator_tag) {If (first! = Last) {size_type n = 0; distance (first, last, n); If (size_type (end_of_storage-finish)> = N) {const size_type elems_after = finish-position; iterator old_finish = finish; If (elems_after> N) {uninitialized_copy (finish-N, finish, finish); finish + = N; copy_backward (Position, old_finish-N, old_finish ); copy (first, last, position);} else {forwarditerator mid = first; advance (MID, elems _ After); uninitialized_copy (MID, last, finish); finish + = N-elems_after; uninitialized_copy (Position, old_finish, finish); finish + = elems_after; copy (first, mid, position) ;}} else {const size_type old_size = size (); const size_type Len = old_size + max (old_size, n); iterator new_start = data_allocator: allocate (LEN ); iterator new_finish = new_start; _ stl_try {new_finish = uninitialized_cop Y (START, position, new_start); new_finish = uninitialized_copy (first, last, new_finish); new_finish = uninitialized_copy (Position, finish, new_finish );} # ifdef _ stl_use_exceptions catch (...) {destroy (new_start, new_finish); data_allocator: deallocate (new_start, Len); throw;} # endif/* _ stl_use_exceptions */destroy (START, finish ); deallocate (); Start = new_start; finish = new_finish; end_of_s Torage = new_start + Len ;}}# else/* _ stl_member_templates */template <class T, class alloc> void vector <t, alloc>: insert (iterator position, const_iterator first, const_iterator last) {If (first! = Last) {size_type n = 0; distance (first, last, n); If (size_type (end_of_storage-finish)> = N) {const size_type elems_after = finish-position; iterator old_finish = finish; If (elems_after> N) {uninitialized_copy (finish-N, finish, finish); finish + = N; copy_backward (Position, old_finish-N, old_finish ); copy (first, last, position);} else {uninitialized_copy (first + elems_after, last, F Inish); finish + = N-elems_after; uninitialized_copy (Position, old_finish, finish); finish + = elems_after; copy (first, first + elems_after, position );}} else {const size_type old_size = size (); const size_type Len = old_size + max (old_size, n); iterator new_start = data_allocator: allocate (LEN); iterator new_finish = new_start; _ stl_try {new_finish = uninitialized_copy (START, position, new_s Tart); new_finish = uninitialized_copy (first, last, new_finish); new_finish = uninitialized_copy (Position, finish, new_finish);} # ifdef _ stl_use_exceptions catch (...) {destroy (new_start, new_finish); data_allocator: deallocate (new_start, Len); throw;} # endif/* _ stl_use_exceptions */destroy (START, finish ); deallocate (); Start = new_start; finish = new_finish; end_of_storage = new_start + Len ;}}# Endif/* _ stl_member_templates */# If defined (_ SGI )&&! Defined (_ gnuc _) & (_ mips_sim! = _ Mips_sim_abi32) # pragma reset woff 1174 # endif _ stl_end_namespace # endif/* _ sgi_stl_internal_vector_h * // local variables: // mode: C ++/end:


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.