Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is vector implemented in C++

I am thinking of how I can implement std::vector from the ground up.

How does it resize the vector?

realloc only seems to work for plain old stucts, or am I wrong?

like image 388
John Smith Avatar asked Jun 17 '10 18:06

John Smith


People also ask

How is vector internally implemented?

Vector is implemented as a dynamically allocated array. The memory for this array is allocated in the constructor. As more elements are inserted the array is dynamically increased in size. A constructor without parameter creates an array with a default size.

What is vector how it implement as dynamic array?

A vector is a dynamic array, whose size can be increased, whereas THE array size can not be changed. Reserve space can be given for vector, whereas for arrays you cannot give reserved space. A vector is a class whereas an array is a datatype.

How are STD vectors implemented?

It's implemented by using an underlying array. It's not possible to implement a std::vector<T> with a linked list because the standard guarantees the elements in the list will be held in contiguous memory. Also, lookup time is important.

How does a vector work in C++?

Vectors in C++ are sequence containers representing arrays that can change in size. They use contiguous storage locations for their elements, which means that their elements can also be accessed using offsets on regular pointers to its elements, and just as efficiently as in arrays.


1 Answers

it is a simple templated class which wraps a native array. It does not use malloc/realloc. Instead, it uses the passed allocator (which by default is std::allocator).

Resizing is done by allocating a new array and copy constructing each element in the new array from the old one (this way it is safe for non-POD objects). To avoid frequent allocations, often they follow a non-linear growth pattern.

UPDATE: in C++11, the elements will be moved instead of copy constructed if it is possible for the stored type.

In addition to this, it will need to store the current "size" and "capacity". Size is how many elements are actually in the vector. Capacity is how many could be in the vector.

So as a starting point a vector will need to look somewhat like this:

template <class T, class A = std::allocator<T> > class vector { public:     // public member functions private:     T*                    data_;     typename A::size_type capacity_;     typename A::size_type size_;     A                     allocator_; }; 

The other common implementation is to store pointers to the different parts of the array. This cheapens the cost of end() (which no longer needs an addition) ever so slightly at the expense of a marginally more expensive size() call (which now needs a subtraction). In which case it could look like this:

template <class T, class A = std::allocator<T> > class vector { public:     // public member functions private:     T* data_;         // points to first element     T* end_capacity_; // points to one past internal storage     T* end_;          // points to one past last element     A  allocator_; }; 

I believe gcc's libstdc++ uses the latter approach, but both approaches are equally valid and conforming.

NOTE: This is ignoring a common optimization where the empty base class optimization is used for the allocator. I think that is a quality of implementation detail, and not a matter of correctness.

like image 151
Evan Teran Avatar answered Oct 12 '22 23:10

Evan Teran