Implemented a simple vector-like structure. I would appreciate all
criticism relevant to code, style, flow, camelCase vs underscore, and so
forth.
template <class T>
class Vector {
public:
typedef T* Iterator;
Vector();//Default constructor
Vector(unsigned int size);//Constructor with size only
Vector(unsigned int size, const T & initial);//Ctor with size & initials
Vector(const Vector<T>& v); //copy constructor
~Vector();
unsigned int capacity() const;
unsigned int size() const;
bool empty() const;
Iterator begin();
Iterator end();
T& front();
T& back();
void push_back(const T& value);
void pop_back();
void reserve(unsigned int capacity);
void resize(unsigned int size);
T & operator[](unsigned int index);
Vector<T> & operator = (const Vector<T> &);
void clear();
private:
unsigned int _size;
unsigned int _capacity;
unsigned int Log;
T* buffer;
};
template<class T>
Vector<T>::Vector() {
_capacity = 0;
_size = 0;
buffer = 0;
Log = 0;
}
template<class T>
Vector<T>::Vector(const Vector<T> & v) {
_size = v._size;
Log = v.Log;
_capacity = v._capacity;
buffer = new T[_size];
for (unsigned int i = 0; i < _size; i++)
buffer[i] = v.buffer[i];
}
template<class T>
Vector<T>::Vector(unsigned int size) {
_size = size;
Log = ceil(log((double) size) / log(2.0));
_capacity = 1 << Log;
buffer = new T[_capacity];
}
template <class T>
bool Vector<T>:: empty() const {
return _size == 0;
}
template<class T>
Vector<T>::Vector(unsigned int size, const T& initial) {
_size = size;
Log = ceil(log((double) size) / log(2.0));
_capacity = 1 << Log;
buffer = new T [_capacity];
for (unsigned int i = 0; i < size; i++)
buffer[i] = initial;
}
template<class T>
Vector<T>& Vector<T>::operator = (const Vector<T> & v) {
delete[] buffer;
_size = v._size;
Log = v.Log;
_capacity = v._capacity;
buffer = new T [_capacity];
for (unsigned int i = 0; i < _size; i++)
buffer[i] = v.buffer[i];
return *this;
}
template<class T>
typename Vector<T>::Iterator Vector<T>::begin() {
return buffer;
}
template<class T>
typename Vector<T>::Iterator Vector<T>::end() {
return buffer + size();
}
template<class T>
T& Vector<T>::front() {
return buffer[0];
}
template<class T>
T& Vector<T>::back() {
return buffer[_size - 1];
}
template<class T>
void Vector<T>::push_back(const T & v) {
/*
Incidentally, one common way of regrowing an array is to double the size as needed.
This is so that if you are inserting n items at most only O(log n) regrowths are performed
and at most O(n) space is wasted.
*/
if (_size >= _capacity) {
reserve(1 << Log);
Log++;
}
buffer [_size++] = v;
}
template<class T>
void Vector<T>::pop_back() {
_size--;
}
template<class T>
void Vector<T>::reserve(unsigned int capacity) {
T * newBuffer = new T[capacity];
for (unsigned int i = 0; i < _size; i++)
newBuffer[i] = buffer[i];
_capacity = capacity;
delete[] buffer;
buffer = newBuffer;
}
template<class T>
unsigned int Vector<T>::size() const {
return _size;
}
template<class T>
void Vector<T>::resize(unsigned int size) {
Log = ceil(log((double) size) / log(2.0));
reserve(1 << Log);
_size = size;
}
template<class T>
T& Vector<T>::operator[](unsigned int index) {
return buffer[index];
}
template<class T>
unsigned int Vector<T>::capacity()const {
return _capacity;
}
template<class T>
Vector<T>::~Vector() {
delete[] buffer;
}
template <class T>
void Vector<T>::clear() {
_capacity = 0;
_size = 0;
buffer = 0;
Log = 0;
}
Source: http://codereview.stackexchange.com/questions/60484/stl-vector-implementation