I've developed a custom vector class in C++, complete with functionalities like assignment, push_back(), emplace_back(), pop_back(), clear(), and size(). I would greatly appreciate any feedback on design or implementation details to ensure the class is as robust as possible.
#include <iostream>
template<typename T>
class Vector {
private:
T* m_Data = nullptr;
size_t m_Size = 0;
size_t m_Capacity = 0;
void ReAlloc(size_t newCapacity) {
T* newBlock = new T[newCapacity];
for(size_t i = 0; i < m_Size; i++)
newBlock[i] = std::move(m_Data[i]);
m_Capacity = newCapacity;
std::swap(newBlock, m_Data);
delete[] newBlock;
}
public:
Vector();
Vector(size_t size);
Vector(size_t size, const T& initial);
Vector(const Vector& v);
Vector(Vector&& v);
void Push_Back(const T& value);
const T& operator[](size_t index) const;
T& operator[](size_t index);
template<typename... Args>
T& EmplaceBack(Args&&... args);
void PopBack();
void Clear();
size_t Size() const {return m_Size;}
};
template<class T>
Vector<T>::Vector() {
ReAlloc(2);
m_Size = 0;
}
template<class T>
Vector<T>::Vector(size_t size) {
ReAlloc(size * 2 + 1);
m_Size = size;
}
template<class T>
Vector<T>::Vector(size_t size, const T& initial) {
ReAlloc(size * 2 + 1);
for(size_t i = 0; i < size; i++) m_Data[i] = initial;
m_Size = size;
}
template<class T>
Vector<T>::Vector(const Vector& v) {
ReAlloc(v.m_Capacity);
for(size_t i = 0; i < m_Size; i++) m_Data[i] = v.m_Data[i];
m_Size = v.m_Size;
}
template<class T>
Vector<T>::Vector(Vector&& v) {
ReAlloc(v.m_Capacity);
for(size_t i = 0; i < m_Size; i++) m_Data[i] = v.m_Data[i];
m_Size = v.m_Size;
}
template<class T>
void Vector<T>:: Push_Back(const T& value) {
if(m_Size >= m_Capacity) ReAlloc(m_Capacity * 2 + 1);
m_Data[m_Size] = value;
m_Size++;
}
template<class T>
const T& Vector<T>:: operator[](size_t index) const
{
return m_Data[index];
}
template<class T>
T& Vector<T>:: operator[](size_t index)
{
return m_Data[index];
}
template<class T>
template<typename... Args>
T& Vector<T>:: EmplaceBack(Args&&... args) {
if(m_Size >= m_Capacity) ReAlloc(m_Capacity * 2 + 1);
new(&m_Data[m_Size]) T(std::forward<Args>(args)...);
return m_Data[m_Size++];
}
template<class T>
void Vector<T>:: PopBack() {
if(m_Size > 0) {
m_Size--;
m_Data[m_Size].~T();
}
}
template<class T>
void Vector<T>:: Clear() {
for(size_t i = 0; i < m_Size; i++) m_Data.~T();
m_Size = 0;
}