STL source code analysis-Vector

Source: Internet
Author: User

Overview of vector containers
The data arrangement and operation method of vector are very similar to those of array. The only difference between the two lies in the flexibility of space application. Array is a static space. Once configured, it cannot be changed. To change a large (or small) House, you can configure a new space by the client, then, the elements are moved one by one from the old address to the new address, and then the original space is returned to the system. Vector is a dynamic space. With the addition of elements, its internal mechanism will expand the space to accommodate new elements. Therefore, the use of vector is very helpful for the rational use of memory and the flexibility of application. We no longer need to require an array with a large header at the beginning because we are afraid of insufficient space, we can use array with peace of mind.
The key to the implementation of vector is its control of the size and the efficiency of data Movement During reconfiguration. Once the original space of the vector is fully loaded, if each new element is added to the client, the vector only expands the space of one element, which is actually unwise. Because the so-called extended space (no matter how big), as mentioned earlier, is"Configure new space, move data, and release old space"The big project has a high time cost. We should consider it as a precaution. We can see the Space Configuration Policy of SGI vector later.
In addition, becauseVector maintains a continuous linear space, so vector supports random access..
Note: When a vector is dynamically increased by an hour, it is not a new space after the original space (because it cannot be guaranteed that there is still space available for configuration after the original space ), in addition, a large space is configured twice the original size, and then the original content is copied. Then, new elements are constructed after the original content and the original space is released. Therefore,Any operations on the vector, once space reconfiguration occurs, all iterators pointing to the original vector will become invalid.. This is an easy mistake for programmers. Be careful.
The following is an excerpt from the source code defined by vector:

# Include <iostream> using namespace STD; # include <memory. h> // alloc is the sgi stl space configurator template <class T, class alloc = alloc> class vector {public: // defines the nested type of vector, typedefs is used to provide struct <I> support for typedef t value_type; typedef value_type * pointer; typedef value_type * iterator; typedef value_type & reference; typedef size_t size_type; typedef ptrdiff_t struct; protected: // This provides the STL standard Allocator interface typedef simpl E_alloc <value_type, alloc> data_allocator; iterator start; // indicates the iterator finish of the currently used space header; // indicates the iterator end_of_storage at the end of the currently used space; // void insert_aux (iterator position, const T & X) at the end of the actually allocated memory space; // release the allocated memory space void deallocate () {// because data_allocator is used to allocate memory space, // you must also use data_allocator: deallocate () to release the memory. // if the memory is directly released, if (start) data_allocator: deallocate (START, end_of_storage -Start);} void fill_initialize (size_type N, const T & Value) {start = allocate_and_fill (n, value); finish = start + N; // set the end point of the currently used memory space. // The construction phase. There is not much memory allocated in this implementation. // you need to set the end point of the memory space and, the endpoint of the used memory space is the same as end_of_storage = finish;} public: // get several iterator begin () {return start;} iterator end () {return finish ;} // returns the number of current objects size_type size () const {return size_type (end ()-begin ();} size_type max_size () const {return Size_type (-1)/sizeof (t);} // returns the maximum number of objects that can be stored before the memory is reassigned. 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);} // in this implementation, the default constructed vector does not allocate memory space. vector (): Start (0 ), finish (0), end_of_storage (0) {} vector (size_type N, const T & Value) {fill_initialize (n, value);} vector (int n, const T & V Alue) {fill_initialize (n, value);} vector (long N, const T & Value) {fill_initialize (n, value );} // The object must provide the default constructor 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 ;}~ Vector () {// destructor destroy (START, finish); // release memory deallocate () ;}vector <t, alloc> & operator = (const vector <t, alloc> & X); // provides the access function reference Front () {return * begin ();} reference back () {return * (end ()-1 );} //////////////////////////////////////// //////////////////////////////////////// // append an element to the end of the container, the memory may be re-allocated /////////////////////////////////// //////////////////////////////////////// //// // push_back (Const T & X) // | ---------------- is the capacity full? /// | // -------------------------- // No | Yes // | // returns complete // construct (finish, x); insert_aux (end (), X ); // ++ finish; | // | ------ the memory is insufficient, and the resource is reassigned. // | the size is twice the original size. // new_finish = data_allocator: allocate (LEN ); <stl_alloc.h> // uninitialized_copy (START, position, new_start); <stl_uninitialized.h> // construct (new_finish, x); <stl_construct.h> // ++ new_finish; // uninitialized_copy (Position, finish, new_finish ); <Stl_uninitialized.h> ///////////////////////////////////// //////////////////////////////////////// /// void push_back (const T & X) {// if the memory meets the conditions, directly append the element. Otherwise, you need to re-allocate the memory space if (finish! = End_of_storage) {construct (finish, x); ++ finish;} elseinsert_aux (end (), x );} //////////////////////////////////////// //////////////////////////////////////// // Insert the element at the specified position ///////////////////////////////// //////////////////////////////////////// //////// insert (iterator position, const T & X) // | ------------ is the capacity sufficient? & is it end ()? // | // --------------------------------------------- // No | Yes // | // response parameters // insert_aux (Position, x); construct (finish, X ); // | ++ finish; // | -------- is the capacity sufficient? // | // ---------------------------------------------------- // Yes | no // | // returns | // construct (finish, * (finish-1 )); | // ++ finish; | // t x_copy = x; | // copy_backward (Position, finish-2, finish-1); | // * position = x_copy; | // activities // data_allocator: allocate (LEN); <stl_alloc.h> // uninitialized_copy (START, position, new_start); <stl_uninitialized.h> // construct (new_finish, X ); <stl_construct.h> // ++ New_finish; // uninitialized_copy (Position, finish, new_finish); <stl_uninitialized.h> // destroy (begin (), end (); <stl_construct.h> // deallocate (); //////////////////////////////////////// //////////////////////////////////////// iterator insert (iterator position, const T & X) {size_type n = position-begin (); If (finish! = End_of_storage & position = end () {construct (finish, x); ++ finish;} elseinsert_aux (Position, x); Return begin () + N ;} iterator insert (iterator position) {return insert (Position, T ();} void pop_back () {-- finish; destroy (finish);} iterator erase (iterator position) {If (Position + 1! = End () Copy (Position + 1, finish, position); -- finish; destroy (finish); Return position;} iterator erase (iterator first, iterator last) {iterator I = copy (last, finish, first); // destructor destroy (I, finish); finish = finish-(last-first ); return first;} // adjust the size, but the memory space void resize (size_type new_size, const T & X) {If (new_size <size () is not re-allocated ()) erase (begin () + new_size, end (); elseinsert (end (), new_size -Size (), x);} void resize (size_type new_size) {resize (new_size, T ();} void clear () {erase (begin (), end ();} protected: // allocate space, and copy the object to the allocated space iterator allocate_and_fill (size_type N, const T & X) {iterator result = data_allocator :: allocate (n); uninitialized_fill_n (result, n, x); return result ;} // provide the insert operation /////////////////////////////////// //////////////////////////////////////// //// // insert_aux (iterat Or position, const T & X) // | ---------------- is the capacity sufficient? // Items // ------------------------------------------- // Yes | no // | // starting from opsition, move a position backward. | // construct (finish, * (finish-1); | // ++ finish; | // t x_copy = x; | // copy_backward (Position, finish-2, finish-1 ); | // * position = x_copy; | // bytes // data_allocator: allocate (LEN); // uninitialized_copy (START, position, new_start); // construct (new_finish, x); // ++ new_finish; // uninitialized_copy (Position, finish, new_finish); // destroy (begin (), end (); // deallocate (); //////////////////////////////////////// //////////////////////////////////////// template <class t, class alloc> void insert_aux (iterator position, const T & X) {If (finish! = End_of_storage) // There is a backup space {// construct an element at the beginning of the backup space, and use the last element value of the vector as its initial value construct (finish, * (finish-1); ++ finish; t x_copy = x; copy_backward (Position, finish-2, finish-1); * position = x_copy ;} else // no available space {const size_type old_size = size (); const size_type Len = old_size! = 0? 2 * old_size: 1; // The above configuration elements: If the size is 0, configure 1 (the size of each element) // If the size is not 0, configure twice the original size // the first half to place the original data, and the second half to place the new data iterator new_start = data_allocator: allocate (LEN ); // The actual configuration of iterator new_finish = new_start; // reconfigure the memory. Try {// copy the content before the original insertion point of the original vector to the new vectornew_finish = uninitialized_copy (START, position, new_start); // set the initial value xconstruct (new_finish, x) for the new element; // adjust the water level + + new_finish; // copy the original content after the Plugging Point to new_finish = uninitialized_copy (posit Ion, finish, new_finish);} catch (...) {// rollback operation destroy (new_start, new_finish); data_allocator: deallocate (new_start, Len); throw;} // analyze and release the original vectordestroy (begin (), end (); deallocate (); // adjust the iterator to point to the new vectorstart = new_start; finish = new_finish; end_of_storage = new_start + Len ;}} //////////////////////////////////////// //////////////////////////////////////// // insert n elements at the specified position /////////////////////////////// /////// //////////////////////////////////////// /// Insert (iterator position, size_type N, const T & X) // | ------------------ is the number of inserted elements 0? // Configure // ------------------------------------------- // No | Yes // | returns // | return; // | ----------- is the memory sufficient? // | // --------------------------------------------------- // Yes | no // | ------ (finish-position)> n? | // | Adjust the pointer separately | // adjust | // ---------------------------- | // No | Yes | // adjust the pointer | // insert operation, adjust the pointer insert operation and adjust the pointer | // bytes // data_allocator: allocate (LEN); // new_finish = uninitialized_copy (START, position, new_start ); // new_finish = uninitialized_fill_n (new_finish, n, x); // new_finish = uninitialized_copy (Position, finish, new_finish); // destroy (START, finish ); // deallocate ();//////////////////////////// //////////////////////////////////////// /// // Template <class t, class alloc> void insert (iterator position, size_type N, const T & X) {// if n is 0, no operation is performed if (n! = 0) {If (size_type (end_of_storage-finish)> = N) {// The remaining spare space is greater than or equal to "Number of new elements" t x_copy = X; // calculate the number of existing elements after the insertion point. Const size_type elems_after = finish-position; iterator old_finish = finish; If (elems_after> N) {// The number of existing elements after the insertion point is greater than the number of new elements. uninitialized_copy (finish-N, finish, finish); finish + = N; // mark the end of the vector with copy_backward (Position, old_finish-N, old_finish); fill (Position, Position + N, x_copy ); // enter a new value from the insertion point} else {// The number of existing elements after the insertion point is less than or equal to the 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 remaining spare space is smaller than the "Number of new elements" (additional memory must be configured) // determine the new length first: double the length, or the old Length + number of new elements const size_type old_size = size (); const size_type Len = old_size + max (old_size, N ); // configure the new vector space iterator new_start = data_allocator: allocate (LEN); iterator new_finish = new_start; __stl_try {// first copy the element before the insertion point of the old vector to the new space new_finish = uninitialized_copy (START, position, new_start ); // enter the new element (the initial values are all N) in the new space new_finish = uninitialized_fill_n (new_finish, n, x ); // copy the element after the insertion point of the old vector to the new space new_finish = uninitialized_copy (Position, finish, new_finish);} # ifdef _ stl_use_exceptionscatch (...) {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 ;}}}};

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.