Principles and implementation of vector in STL Series

Source: Internet
Author: User

I 've been so busy recently, but I still want to write something of my own. I don't know what to write. Finally, I decided to try to implement several collections commonly used in STL by myself, to deepen my understanding of STL, and to see if I have the ability to implement it. The implementation goal is: 1 to be compatible with STL; 2 to maximize the implementation of STL interfaces and maintain consistency. I can replace the set in STL with the one I wrote. This blog introduces the principles and implementations of vector.

Let's take a rough look at the implementation of vector. The complete source code will be provided later.

Add element: the Vector stores elements through a continuous array. If the set is full, a larger memory will be allocated when new data is added, and the original data will be copied, release the memory and insert new elements. Insert new data, insert push_back at the end, and insert data at any position through the iterator. Here we will talk about inserting data through the iterator, the distance between the iterator and the first element indicates the position to be inserted, that is, int index = iter-begin (). All the elements after this element move backward to a position and store the new element in the blank position.

 

        void insert(const_iterator iter,const T& t )        {              int index=iter-begin();            if (index<size_)            {                if (size_==capacity_)                {                    int capa=calculateCapacity();                    newCapacity(capa);                }                memmove(buf+index+1,buf+index,(size_-index)*sizeof(T));                 buf[index]=t;                size_++;            }         }

 

Delete element: delete is similar to add. Delete the last element pop_back and use the iterator to delete any element erase (iter ). To delete an element through the iterator, you must first find the position of the element to be deleted, that is, int index = iter-begin (). Each element after this position wants to move the position of the previous element. At the same time, we know that erase does not release memory and only initializes to the default value.

Clear: erase is called cyclically. Therefore, when all elements are deleted, the memory is not released. The memory is released in the destructor.

 

        iterator erase(const_iterator iter)        {            int index=iter-begin();             if (index<size_ && size_>0)            {                memmove(buf+index ,buf+index+1,(size_-index)*sizeof(T));                 buf[--size_]=T();            }             return iterator(iter);         }

 

Iteraotr is an important component of STL. iterator can easily store elements in a set. STL writes an iterator for each set. The iterator packs a pointer and implements some common methods, such as ++ ,--,! =, =, *,->, Etc. You can use these methods to find the current element or other elements. vector is a special element in the STL set. Because every element in the vector is continuous, you can replace it with a pointer when implementing the vector yourself, such as typedef T * iterator; typedef const T * const_iterator. If the function in STL can easily operate the set written by itself, it is best to implement an iterator that inherits std: iterator <std: forward_iterator_tag, T>. The iterator that I implement vector is like this:

Template <typename T>

Class viterator: public std: iterator <std: forward_iterator_tag, T> {}

The complete code is provided later. The source code of std: iterator <std: forward_iterator_tag, T> is as follows:

template<class _Category,    class _Ty,    class _Diff = ptrdiff_t,    class _Pointer = _Ty *,    class _Reference = _Ty&>    struct iterator    {    // base type for all iterator classes           typedef _Category iterator_category;           typedef _Ty value_type;           typedef _Diff difference_type;           typedef _Diff distance_type;    // retained           typedef _Pointer pointer;           typedef _Reference reference;    };

 

Iterator does not have any Members, but only defines a set of types, so inheriting it will not make your struct larger. This set of types is the Internal Contract of STL, functions in STL assume that each iterator defines these types, so as long as your iterator defines these types, they can be used together with the STL function set.

The source code of my vector implementation is as follows:

# Ifndef _ CVECTOR_H _ # define _ CVECTOR_H _ namespace cth {template <typename T> class viterator: public std: iterator <std: forward_iterator_tag, T> {public: viterator () {t = NULL;} viterator (T * t _) {t = t _;} viterator (const viterator & other) {t = other. t;} viterator & operator = (const viterator & other) {t = other. t; return * this;} viterator & operator ++ () {t ++; return * this;} viterator operator ++ (int) {v Iterator iter = * this; t ++; return iter;} viterator & operator + (int count) {t + = count; return * this;} viterator & operator --() {t --; return * this;} viterator operator -- (int) {viterator iter = * this; t --; return iter;} viterator & operator-(int count) {t-= count; return * this;} int operator-(const viterator & other) {return t-other.t;} int operator-(const viterator & other) const {return t-other.t;} T & operator * () {return * t;} const T & operator * () const {return * t;} T * operator-> () {return t ;} const T * operator-> () const {return t;} inline bool operator! = (Const viterator & other) {return t! = Other. t;} inline bool operator! = (Const viterator & other) const {return t! = Other. t;} inline bool operator = (const viterator & other) {return t = other. t;} inline bool operator = (const viterator & other) const {return t = other. t;} inline bool operator <(const viterator & other) {return t <other. t;} inline bool operator <(const viterator & other) const {return t <other. t;} inline bool operator <= (const viterator & other) {return t <= other. t;} inline bool operator <= (const vite Rator & other) const {return t <= other. t;} inline bool operator> (const viterator & other) {return t> other. t;} inline bool operator> (const viterator & other) const {return t> other. t;} inline bool operator >=( const viterator & other) {return t> = other. t;} inline bool operator >=( const viterator & other) const {return t> = other. t;} private: T * t;}; template <typename T> class cvector {public: typedef v Iterator <T> iterator; // viterator <T> is a pointer packaging, so you can use T * to replace viterator <T> typedef const viterator <T> const_iterator; // typedef T * iterator; // typedef const T * const_iterator; cvector () {initData (0);} cvector (int capa, const T & val = T ()) {initData (capa); newCapacity (capacity _); for (int I = 0; I <size _; I ++) buf [I] = val ;} cvector (const_iterator first, const_iterator last) {initData (last-first); newCapacit Y (capacity _); iterator iter = iterator (first); int index = 0; while (iter! = Last) buf [index ++] = * iter ++ ;}~ Cvector () {if (buf) {delete [] buf; buf = NULL;} size _ = capacity _ = 0;} void clear () {if (buf) erase (begin (), end ();} void push_back (const T & t) {if (size _ = capacity _) {int capa = calculateCapacity (); newCapacity (capa);} buf [size _ ++] = t;} void pop_back () {if (! Empty () erase (end ()-1);} void insert (const_iterator iter, const T & t) {int index = iter-begin (); if (index <size _) {if (size _ = capacity _) {int capa = calculateCapacity (); newCapacity (capa);} memmove (buf + index + 1, buf + index, (size _-index) * sizeof (T); buf [index] = t; size _ ++ ;}} iterator erase (const_iterator iter) {int index = iter-begin (); if (index <size _ & size _> 0) {memmove (buf + index, buf + index + 1 ,( Size _-index) * sizeof (T); buf [-- size _] = T ();} return iterator (iter);} iterator erase (const_iterator first, const_iterator last) {iterator first _ = iterator (first); iterator last _ = iterator (last); while (first _ <= last _ --) erase (first _); return iterator (first _);} T & front () {assert (size _> 0); return buf [0];} T & back () {assert (size _> 0); return buf [size _-1];} T & at (int index) {assert (size _> 0); return Buf [index];} T & operator [] (int index) {assert (size _> 0 & index> = 0 & index <size _); return buf [index];} bool empty () const {return size _ = 0;} int size () const {return size _;} int capacity () const {return capacity _;} iterator begin () {return iterator (& buf [0]);} iterator end () {return iterator (& buf [size _]);} private: void newCapacity (int capa) {capacity _ = capa; T * newBuf = new T [capacity _]; If (buf) {memcpy (newBuf, buf, size _ * sizeof (T); delete [] buf;} buf = newBuf;} inline int calculateCapacity () {return capacity _ * 3/2 + 1;} inline void initData (int capa) {buf = NULL; size _ = capacity _ = capa> 0? Capa: 0;} int size _; int capacity _; T * buf ;};}View Code

The instance code-level running result is as follows:

Struct Point {Point (int x _ = 0, int y _ = 0): x (x _), y (y _) {} int x, y ;}; bool operator <(const Point & p1, const Point & p2) {if (p1.x <p2.x) {return true;} else if (p1.x> p2.x) {return false ;} return p1.y <p2.y;} void cvectorTest () {cvector <Point> vect; for (int I = 0; I <10; I ++) {Point p (I, i); vect. push_back (p);} cvector <Point >:: iterator iter = vect. begin (); while (iter! = Vect. end () {cout <"[" <iter-> x <"" <iter-> y <"],"; ++ iter ;} iter = vect. begin () + 5; vect. insert (iter, Point (55,55); iter = vect. end ()-3; vect. insert (iter, Point (77,77); cout <endl <"after inserting two elements:" <endl; iter = vect. begin (); while (iter! = Vect. end () {cout <"[" <iter-> x <"" <iter-> y <"],"; ++ iter ;} std: sort (vect. begin (), vect. end (); cout <endl <"after sorting:" <endl; iter = vect. begin (); while (iter! = Vect. end () {cout <"[" <iter-> x <"" <iter-> y <"],"; ++ iter ;} vect. erase (vect. begin () + 10); vect. erase (vect. begin () + 10); cout <endl <"Delete two new elements" <endl; iter = vect. begin (); while (iter! = Vect. end () {cout <"[" <iter-> x <"" <iter-> y <"],"; ++ iter ;} vect. clear (); cout <endl <"after clear is executed" <endl; cout <"size =" <vect. size () <", capacity =" <vect. capacity (); cvector <Point> vect1; for (int I = 10; I <20; I ++) {Point p (I, I ); vect1.push _ back (p);} cout <endl <"Copy data from another cvector:" <endl; cvector <Point> vect2 (vect1.begin (), vect1.end (); vect2.pop _ back (); vect2.pop _ back (); for (int I = 0; I <vect2.size (); I ++) {cout <"[" <vect2 [I]. x <"," <vect2 [I]. y <"]," ;}cout <endl ;}

The implementation of list, set, and map will be available later. Please wait ......

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.