Implementation of the 4.STL simple container (cghvector)

Source: Internet
Author: User

The program I wrote with VS2013 (GitHub), the vector version of the code is located inCghstl/version/Cghstl-0.3.1.rar

I am according to Houtie Teacher's "STL Source Analysis" Do Cghstl, now only see the third chapter, think this book is very suitable for self-study.

The first chapter explains the Space Configurator, which is the most basic part of STL, nothing to say.


The second chapter explains the iterator, the teacher raised the example of a one-way list, which is very sophisticated, one-way linked list does not require continuous storage space, meaning that the use of a one-way list to implement the container does not need to consider the problem of space overflow, we can focus on the container iterator.


The third chapter explains the sequence container, the first section introduces the vector implementation, the vector needs to consider the space continuous use and the space overflow and so on, but because the vector maintains the continuous linear space, regardless of its element type, The normal pointer can be used as a vector iterator to meet all necessary conditions! This succeeds in avoiding the design of the container when you have to scatter the energy to design the pit of the iterator!


Houtie Teacher Write a book is really level Ah!


So, let's take a look at the implementation details of a vector.


We have a total of four documents:

1. GlobalConstruct.h, construction and destructor files , located in allocator/cghallocator

2. CghAlloc.h, Space configurator file , located under allocator/cghallocator folder

3. CghVector.h, container implementation file, located inCghstl/Sequence Containers/Cghvector/

4. cghSTL.cpp, test file, located inCghstl/Test/

Look first, globalConstruct.h. constructor file

/********************************************************************  Copyright (c) Chen gonghao* all  Rights reserved.**  [email protected]**  function: Implementation code for global construction and destruction ************************************************** /#include "stdafx.h" #include <new.h> #include <type_traits> #ifndef _cgh_global_ Construct_#define _cgh_global_construct_namespace cgh{#pragma region Unified tectonic destructor Template<class T1, class  t2> inline void construct (t1* p, const t2& value) {new (P) T1 (value);} Template<class t>inline void Destroy (t* pointer) {pointer->~t ();} Template<class forwarditerator>inline void Destroy (ForwardIterator first, ForwardIterator last) {// It was supposed to be here. Using the feature extractor (traits programming technique) to determine whether an element is non-trivial//non-trivial element can directly free memory//trivial element to do call destructor and then free memory for (; first < Last ++first) Destroy (&*first);} #pragma endregion} #endif

In accordance with the STL interface specification, the correct order is to allocate memory first and then construct the element. The implementation of the constructor takes the form of placement new, and for the sake of simplification, I call the destructor directly to destroy the element, and in the case of efficiency, it is generally judged whether the element is a non-trivial type, and the elements of non-trivial can directly free memory. It can be understood that non-trivial are all allocated on the stack, without our concern, the program is automatically recycled, trivial elements to be allocated on the heap, need to manually call the destructor to destroy, and then free memory.

CghAlloc.h is a space configurator file, and the Space Configurator is responsible for memory application and recycling.

/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** function: implementation code for Cghallocator Space Configurator ************************************************** /#ifndef _cgh_alloc_#define _cgh_alloc_#include <new> #include <cstddef> #include < cstdlib> #include <climits> #include <iostream>namespace cgh{#pragma region memory allocation and deallocation functions, element Construction and destructors// Memory allocation Template<class t>inline t* _allocate (ptrdiff_t size, t*) {set_new_handler (0); t* tmp = (t*) (:: Operator new ((size_t) (Size * sizeof (T))), if (TMP = = 0) {Std::cerr << "out of Memory" << std::e Ndl;exit (1);} return TMP;} Memory free template<class t>inline void _deallocate (t* buffer) {:: operator delete (buffer);} Element constructs Template<class T1, class t2>inline void _construct (t1* p, const t2& value) {new (P) T1 (value);} Element destructor Template<class t>inline void _destroy (t* ptr) {ptr->~t ();} #pragma endregion#pragma Region CghalloImplementation of the Cator Space Configurator template<class t>class cghallocator{public:typedef tvalue_type;typedef T*pointer;typedef const T* Const_pointer;typedef t&reference;typedef Const T&AMP;CONST_REFERENCE;TYPEDEF size_tsize_type;typedef ptrdiff_ Tdifference_type;template<class u>struct rebind{typedef cghallocator<u> Other;}; Static pointer allocate (size_type N, const void* hint = 0) {return _allocate ((Difference_type) n, (pointer) 0);} static void Deallocate (pointer p, Size_type N) {_deallocate (P);} void construct (pointer p, const t& value) {_construct (P, value);} void Destroy (pointer p) {_destroy (P);} Pointer address (reference x) {return (pointer) &x;} Const_pointer const_address (Const_reference x) {return (Const_pointer) &x;} Size_type max_size () Const{return size_type (uint_max/sizeof (T));}}; #pragma endregion#pragma region encapsulates the STL standard Space Configurator Interface Template<class T, class Alloc = Cghallocator<t>>class simple _alloc{public:static t* Allocate (size_t N) {return 0 = = n? 0: (t*) Alloc::allocate (N*sizeof (T));} Static t* Allocate (void) {return (t*) alloc::allocate (sizeof (T)); static void Deallocate (t* p, size_t N) {if (0! = N) Alloc::d eallocate (P, n*sizeof (T));} static void Deallocate (t* p) {Alloc::d eallocate (P, sizeof (T));}}; #pragma endregion} #endif


Class Cghallocator is the definition of the Space Configurator class, the main four functions are as follows: Allocate function allocates memory, deallocate function frees memory, construct constructs elements, destroy destructors. These four functions are eventually implemented by invoking the four inline functions of _allocate, _deallocate, _construct, _destroy.

We write our own space Configurator must encapsulate a layer of STL standard interface,

TEMPLATE<CLASST, class Alloc = Cghallocator<t>>class Simple_alloc


The vector implementation code is as follows:

CghVector.h

/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** function: Implementation code of Cghvector container ******************************************************** /#ifndef _cgh_vector_#define _cgh_vector_#include "globalConstruct.h" #include "cghAlloc.h" #include < Memory>namespace Cgh{template<class T, class Alloc = Cghallocator<t>>class cghvector{public:typedef Tvalue_type;typedef value_type*pointer;typedef value_type*iterator;typedef value_type&reference;typedef size_ Tsize_type;typedef ptrdiff_tdifference_type;//typedef __false_typehas_trivial_default_constructor;//typedef __ False_typehas_trivial_copy_destructor;//typedef __false_typehas_trivial_assignment_operator;//typedef __false_ Typehas_trivial_destructor;//typedef __false_typeis_pod_type;protected:typedef Simple_alloc<value_type, alloc > data_allocator; Define Space Configurator iterator Start;iterator finish;iterator end_of_storage;void Insert_Aux (iterator position, const t& value) {if (finish! = end_of_storage) {construct (Finish, * (finish-1)); ++finish; T x_copy = Value;std::copy_backward (position, finish-2, finish-1); *position = x_copy;} else{ptrdiff_t old_size = size (); const Size_type len = old_size! = 0? 2 * old_size:1;/* Configuration principle: If the original size is 0, configure 1 element size if the original size is not 0, then Configure twice times the original size */iterator New_start = data_allocator::allocate (len); iterator new_finish = new_start;try{//put start to position Memory copy to New_start, return new_finish = New_start + (position-start) New_finish = std::uninitialized_copy (start, Position, NE W_start); Construct (new_finish, value); Constructs a new element at New_finish ++new_finish;//new_finish = std::uninitialized_copy (position, Finish, new_finish);} catch (Std::exception ex) {//If execution fails, roll back Destroy (New_start, new_finish);d ata_allocator::d eallocate (New_start, Len); throw;} Destroy (Begin (), End ());d eallocate (); start = New_start;finish = New_finish;end_of_storage = New_start + len;}} #pragma region frees memory and destructor elements void deallocate () {if (start) {daTa_allocator::d eallocate (Start, End_of_storage-start);}} allocating memory and construction elements #pragma endregion#pragma region/* *fill_initialize and Allocate_and_fill Divide the initialization of cghvector into two steps: *1.fill_ Initialize's duty is to allocate a memory *2.fill_initialize call Allocate_and_fill, call the constructor in the allocated memory to create the Cghvector element */void fill_initialize ( Size_type N, const t& value) {start = Allocate_and_fill (n, value); finish = start + N;end_of_storage = finish;} Iterator Allocate_and_fill (size_type N, const t& x) {iterator result = Data_allocator::allocate (n); iterator cur = resu Lt;for (; n > 0;--n, ++cur) {construct (&*cur, x);} return result;} #pragma endregionpublic: #pragma region read operations to Cghvector iterator begin () {return start;}//Returns the address of the Cghvector header element iterator end ( {return finish;}//Returns the address of the Cghvector tail element size_type size () {return size_type (int (end ()-Begin ()));}//Cghvector length = tail element ground Addresses-header element address Size_type capacity () const{return Size_type (End_of_storage-start);}//Cghvector capacity = Maximum capacity address-header element address bool Empty () const {return begin () = = End ();}//Cghvector is empty: headerThe element address is equal to the tail element address reference operator[] (size_type N) {return * (begin () + N);}//returns the element reference at the specified location reference front () {return *begin ( ); }//Get Head element position reference back () {return * (end ()-1)}//Get tail element location #pragma endregion#pragma region constructor Cghvector (): Start (0),  Finish (0), End_of_storage (0) {}//Initialize empty cghvectorcghvector (size_type N, const t& value) {fill_initialize (n, value);} Initializes a cghvectorcghvector (int n, const t& value) that contains n values of value {fill_initialize (n, value);}//Ibid. cghvector (long N, cons T t& value) {fill_initialize (n, value);}//Ibid. explicit Cghvector (size_type N) {fill_initialize (n, T ());}//Initialize CGHVE The length of the ctor is N#pragma endregion #pragma region destructor ~cghvector () {Destroy (start, finish), and//the destructor for the element in Cghvector is called First deallocate ( ); Release Cghvector Memory} #pragma endregion#pragma region writes to cghvector/*** eject tail element */void Pop_back () {--finish;destroy ( finish);} /*** inserts an element at the end of Cghvector */void push_back (const t& x) {//determines if the capacity of Cghvector is full, if not full we construct elements directly on the existing memory area if (finish! = End_ Of_storage) {construct (finiSH, x); ++finish;} else//If it's full we'll reallocate memory and re-constructor {Insert_aux (end (), x);}} /*** clears the element in the [first, last] interval */iterator erase (iterator first, iterator last) {//Put last to finish this element copies the memory space at first as the starting place, Returns the address of First + (finish-last) Iterator i = Std::copy (last, Finish, first);d Estroy (i, finish); Destroy (First + (finish-last), finish] This memory finish = Finish-(Last-first); Reset Finishreturn First;} /*** clears the element at a location */iterator erase (iterator position) {if (position + 1! = End ()) {copy (position + 1, finish, position);} --finish;destroy (finish); return position;} #pragma endregion};} #endif



Cghvector realizes the Pop_back, Push_back, erase.

The comments have been written in sufficient detail. Three standard global functions were called in CghVector.h: Std::copy_backward, Std::uninitialized_copy, Std::copy, three functions.

Test code:

/******************************************************************** Copyright (c) Chen gonghao* All rights reserved.** [email protected]** file name: Test code for Cghvector container ****************************************************** /#include "stdafx.h" #include "cghAlloc.h" #include "globalConstruct.h" #include "cghVector.h" using NAMESPACE::STD;          int _tmain (int argc,_tchar* argv[]) {using NAMESPACE::CGH;         Cghvector<int> Test (2, 2);         cout << "size =" <<test.size () << "\ T";          cout << "capacity =" <<test.capacity () << Endl;         Test.push_back (1);         cout << "size =" <<test.size () << "\ T";          cout << "capacity =" <<test.capacity () << Endl;         Test.push_back (2);         cout << "size =" <<test.size () << "\ T";          cout << "capacity =" <<test.capacity () << Endl;         Test.push_back (3); cout << "SizE = "<<test.size () <<" \ T ";          cout << "capacity =" <<test.capacity () << Endl;         Test.pop_back ();         cout << "size =" <<test.size () << "\ T";          cout << "capacity =" <<test.capacity () << Endl; Std::cout << test[2] << endl;//Returns the element at the specified position, which shows the random access nature of the vector iterator (random access iterators) test.erase (         Test.begin () + 1, test.begin () + 2);         Test.erase (Test.begin ()); For (Cghvector<int>::iterator it =test.begin (); It! = Test.end (); it++) {std::cout &LT;&L T         *it <<std::endl;         } system ("Pause"); return 0;}


You can see that when the size of the cghvector (size) exceeds the capacity (capacity), the cghvector automatically expands to twice times the original.

Implementation of the 4.STL simple container (cghvector)

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.