Source code parsing of STL Vector

Source: Internet
Author: User
Document directory
  • Preface
  • 1. How to implement vector
  • Ii. Vector class definition
  • 3. Insert implementation in Vector
Preface

The project team should implement an algorithm library that involves the implementation of one-dimensional arrays similar to vector. Here, we will learn and understand vector in STL. If you have any questions, please let me know. Thank you.

1. How to implement vector

If you have an interview question, how can we use the data structure to implement the function of Vector in STL? What do you do if you are smart? You may as follows:

  • Perhaps, if you do not consider the allocation efficiency, you only need two members.
    Template
    Class Vector
    {
    Public:
    Vector (INT nlen = 0): m_nlen (nlen), m_data (null)
    {
    If (nlen> 0)
    {
    M_data = new _ ty [nlen];
    }
    }
    Protected:
    _ Ty * m_data;
    Int m_nlen;
    };
  • Perhaps, for example, the following simple idea is implemented:

    # Include

    Using STD: ostream;
    Using STD: istream;

    Class Array {
    Friend ostream & operator <(ostream &, const array &);
    Friend istream & operator> (istream &, array &);

    Public:
    Array (Int = 10 );
    Array (const array &);
    ~ Array ();
    Int getsize () const;

    Const array & operator = (const array &);
    Bool operator = (const array &) const;

    Bool Operator! = (Const array & right) const
    {
    Return! (* This = right );

    }

    Int & operator [] (INT );
    Const Int & operator [] (INT) const;

    PRIVATE:
    Int size;
    Int * PTR;

    };

  • You may say that you should use a template. When the array size changes, the current size will be new directly, and the old or copy or add new items will be added, and then the old m_pdata will be deleted; and m_nlen will be updated;
    When the data size does not change, use m_pdata; directly ;. If you consider the allocation efficiency, you also need a member to store m_nmaxlen; the actual allocation size. Remember to delete the old m_pdata.

Soon, you will realize that, rather than crossing the river without knowing the direction, it is better to directly use the vector implementation code in STL to find out the truth. OK. Next, let's analyze the implementation of STL vector. The analysis is based on the STL source code analysis by Mr. Hou Jie (this book cannot be ignored if you study sgi stl source code), and then you can add your own understanding. I hope it will be helpful to you (the version we will analyze below isSgi stl v2.9).

Ii. Vector class definition

The following are some data members and some member functions in the class defined by vector:

Template
 
  
// Use alloc as the provisioner class vector {public: // (1), (2), (3), (4), (5), representing iterator_traits
  Five types of services. Typedef t value_type; // (1) typedef value_type * pointer; // (2) typedef const value_type * const_pointer; typedef const value_type * const_iterator; typedef value_type & reference; // (3) typedef const value_type & const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; // (4) // The vector maintains a continuous linear empty space, therefore, regardless of the element type, // native indicators can be used as their iterators to meet all requirements. Typedef value_type * iterator;/* according to the preceding statement, if the client writes the following code: Vector
   
    
: Iterator is; Is is shape *, while STL uses iterator_traits.
    
     
: Reference, get shape & use iterator_traits
     
      
: Iterator_category, obtain random_access_iterator_tag (5) (this is the iterator_traits native indicator specific result) * /// some content that is not relevant to the topic of this article is omitted here ....... protected: // exclusive space configurator, each time you configure an element size typedef simple_alloc
      
        Data_allocator; // vector uses a simple continuous linear space. Start and end point respectively to the beginning and end of the Two iterators, // point to the end of the capacity with the iterator end_of_storage. The capacity may be larger than (tail-header). // The excess space is used. 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);} void fill_initialize (size_type N, const T & value) {start = allocate_and_fill (n, value); // configure the space and set the initial value finish = start + N; // adjust the water level end_of_storage = finish; // adjust the water level}
      
     
    
   
 

The following describes the specific implementation of some other member operation functions,

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 {return substring (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 {return * (begin () + n);} vector (): start (0), finish (0), end_of_storage (0) {}// specify the size of 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
 
  
& X) {start = allocate_and_copy (X. end ()-X. begin (), X. begin (), X. end (); finish = start + (X. end ()-X. begin (); end_of_storage = finish;} Template
  
   
Vector (inputiterator first, inputiterator last): Start (0), finish (0), end_of_storage (0) {range_initialize (first, last, iterator_category (first ));} 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); // global function, which constructs/deconstruct basic tools. Deallocate (); // previously defined member function} Vector
   
    
& Amp; operator = (const Vector
    
     
& 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 ;}}
    
   
  
 
3. Insert implementation in Vector

Let's ignore all the disturbing details. Finally, let's analyze them in detail.Insert in Vector(Insert) Implementation of an element:

// Insert n elements starting from position. The initial value of the element is xtemplate.
 
  
Void Vector
  
   
: Insert (iterator position, size_type N, const T & X) {If (n! = 0) {// when n! If (size_type (end_of_storage-finish)> = N) {// The borrow 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: overall move-back finish + = N; // mark the tail end of the vector and move copy_backward (Position, old_finish-N, old_finish); // insert vertex element Move to A', position-> old-finish, and then old_finish fill (Position, Position + N, x_copy ); // enter the new value from the insert point} else {// The number of existing elements after the insert point is less than or equal to the number of new elements. uninitialized_fill_n (finish, N-elems_after, x_copy); // 1. add element x_copy to finish + = N-elems_after; // 2. move n_elems_after uninitialized_copy (Position, old_finish, finish) after finish; // 3. free up space, position-> old_finish finish + = elems_after; // 4. finish and move fill (Position, old _ Finish, x_copy); // 5. insert a new element, (x_copy) Position-> old_finish} else {// The borrow space is smaller than the "Number of new elements" (additional memory must be configured) // first determine the new length: twice the old length, or the old Length + the 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 below :: allocate (LEN); iterator new_finish = new_start; _ stl_try {// first copy the elements before the insertion point of the old vector to the new space. New_finish = uninitialized_copy (START, position, new_start); // enter the new elements (initial values are N) in the new space. New_finish = uninitialized_fill_n (new_finish, n, x); // copy the elements after the insertion point of the old vector to the new space. New_finish = uninitialized_copy (Position, finish, new_finish) ;}# ifdef _ stl_use_exceptions catch (...) {// if an exception occurs, implement "commit or rollback" semantics. 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 (); // the following indicator indicates start = new_start; finish = new_finish; end_of_storage = new_start + Len ;}}}
  
 

I think, if this article only gives the above Code, you must be very angry, saying: dizzy, what is a ghost analysis, add comments to a lot of code, it looks like a bunch of garbled characters. What do you mean. Yes, I think, the reader certainly did not understand the above insert implementation, so below, please allow me to reference the STL source code to analyze the three pictures in the book, I believe, after reading the picture, you willInsert implementation in VectorClear:

As follows:Figure 4-3 B-1As shown in the following figure, the Standby space is 2 and the new element is 2. Therefore, the Standby space> = number of new elements, the number of elements after the insertion point is 3 greater than the number of new elements 2 (the number of original elements 3 + the reserve space is 2, a total of 5 storage units ). In this case,It is equivalent to moving the original three elements after the insertion point to two units.And then insert the two elements to be added from the insert point. The new two elements can be added and the original three elements are stored in five units of space.

As follows:Figure 4-3 B-2As shown in, the number of existing elements after the insertion point is 2 <= number of new elements 3. The processing method is as follows:It is equivalent to moving the original three elements after the insertion point to three units.And then Insert the new three elements from the original insertion point:

If the original space is not enough, the vector will dynamically increase the size, it does not mean that the original space is connected to a new space continuously (because there is still space available for configuration after the original space cannot be guaranteed), but another large space is configured twice the original size, then copy the original content, and then start to construct new elements after the original content, and release the original space. This can be done from the second part of the above insert implementation, when the borrow space is smaller than "add element number" (additional memory must be configured), you can see it.

As follows:Figure 4-3-3(In addition, it must be noted that after the above operations, once space reconfiguration occurs, all iterators pointing to the original vector will become invalid. This is a common mistake. Be careful. -- Said Hou Jie ):

Iv. Vector Extension

Finally, I paste a piece of code, which is equivalent to the efficient application of vector (or expansion ):

/* Copyright (c) 2007-2011 imatix Corporation copyright (c) 2007-2011 other contributors as noted in the authors file this file is part of 0mq. 0mq is free software; you can redistribute it and/or modify it under the terms of the GNU lesser General Public License as published by the Free Software Foundation; either version 3 of the license, or (at your option) any later version. 0mq is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a participant purpose. see the GNU lesser General Public License for more details. you shoshould have your ed a copy of the GNU lesser General Public License along with this program. if not, see 
  
# Include // W ++ // in terms of personal style, it is generally necessary to reject all inline usage of member functions of this type. Namespace zmq {// base class for objects stored in the array. note that each object can // be stored in at most one array. class array_item_t {public: inline array_item_t (): array_index (-1) {}// The Destructor doesn't have to be virtual. it is mad virtual // just to keep ICC and code checking tools from complaining. inline virtual ~ Array_item_t () {} inline void set_array_index (INT index _) {array_index = index _;} inline int get_array_index () {return array_index;} PRIVATE: int array_index; array_item_t (const array_item_t &); const array_item_t & operator = (const array_item_t &) ;}; // STL vector is a simple and efficient container for inserting and deleting elements at the end, the algorithm time complexity is O (1) constant order. The insertion and deletion of other elements are O (n) linear order. // n is the number of elements in the vector container. The vector has an automatic memory management function. For element insertion and deletion, the occupied memory space can be dynamically adjusted. // Fast array implementation with O (1) Access to item, insertion and // removal. array stores pointers rather than objects. The objects have // to be derived from array_item_t class. Template
  
   
Class array_t {public: typedef typename STD: Vector
   
    
: Size_type; inline array_t () {} inline ~ Array_t () {} inline size_type size () {return items. size ();} inline bool empty () {return items. empty ();} inline T * & operator [] (size_type index _) {return items [index _];} inline void push_back (T * Item _) {If (Item _) Item _-> set_array_index (items. size (); items. push_back (Item _);} inline void erase (T * Item _) {erase (Item _-> get_array_index ();} inline void erase (size_type index _) {If (items. back () // The back function returns the reference items of the last element. back ()-> set_array_index (index _); items [index _] = items. back (); items. pop_back ();} inline void swap (size_type index1 _, size_type index2 _) {// exchange sequence number and content if (items [index1 _]) items [index1 _]-> set_array_index (index2 _); If (items [index2 _]) items [index2 _]-> set_array_index (index1 _); STD :: swap (items [index1 _], items [index2 _]);} inline void clear () {items. clear ();} inline size_type index (T * Item _) {return (size_type) Item _-> get_array_index ();} PRIVATE: typedef STD: Vector
    
     
Items_t; items_t items; array_t (const array_t &); const array_t & operator = (const array_t &) ;}# endif
    
   
  
 

Description: @ 555: In the WTF module of WebKit, the vector in it directly gives up the STL vector. It uses Google's tcmalloc to manage the memory, which is more efficient than STL.

Reference: Analysis of STL source code of Mr. Hou Jie.

OK. If you have any questions, please leave it blank. .

Article by: http://blog.csdn.net/v_july_v/article/details/6681522

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.