c++ – Implementation of the std::vector class


Looking forward to get your feedback on my attempt to replicate vector class functionality. Especially I have doubts about copy constructor and resize methods. I think that copy constructor could potentially cause memory leak, but I don’t know how to make it better. I implemented two resize methods and they both seem to work, but which is actually better?

#include <iostream>
#include <type_traits>
#include <math.h>

template <typename T>
class Vector {
private:
    T* m_Data;
    size_t m_Size, m_Capacity;
public:
    Vector(size_t cap = 2)
        : m_Size(0), m_Capacity(cap) {
        m_Data = new T(cap);
    }
    
    Vector(size_t size, size_t cap)
        : m_Size(size), m_Capacity(cap) {
        m_Data = new T(cap);
    }

    Vector(const std::initializer_list<T>& il)
        : Vector(il.size(), il.size() * 2) {
        int cnt = 0;
        for (const auto& el : il)
            m_Data(cnt++) = el;
    }
   
    // copy constructor, makes deep copy
    Vector(const Vector& v)
        : m_Size(v.size()), m_Capacity(v.capacity()) {
        m_Data = new T(m_Capacity);
        for (size_t i = 0; i < m_Size; i++) {
            m_Data(i) = v(i);
        }
    }
    
    ~Vector() {
        delete() m_Data;
    }

//    void resize(size_t newCapacity) {
//        T* newData = new T(newCapacity);
//        m_Size = std::min(m_Size, newCapacity);
//
//        for (size_t i = 0; i < m_Size; i++)
//            newData(i) = std::move(m_Data(i));
//
//        delete() m_Data;
//        m_Data = newData;
//        m_Capacity = newCapacity;
//    }
    
    void resize(size_t newCapacity) {
        char* newData = new char(sizeof(T) * newCapacity);
        m_Size = std::min(m_Size, newCapacity);
        
        T* dst = reinterpret_cast<T*>(newData);
        for (size_t i = 0; i < m_Size; i++)
            new (dst + i) T(m_Data(i));
        
        delete() m_Data;
        m_Data = reinterpret_cast<T*>(newData);
        m_Capacity = newCapacity;
    }
    

        
    void push_back(const T& n) {
        if (m_Capacity <= m_Size)
            resize(m_Capacity * 2);
    
        m_Data(m_Size++) = n;
    }
    
    void push_back(const T&& n) {
        if (m_Capacity <= m_Size)
            resize(m_Capacity * 2);
    
        m_Data(m_Size++) = std::move(n);
    }
    
    void pop_back() {
        if (m_Size > 0)
            m_Data(--m_Size).~T();
    }

    void clear() {
        for (size_t i = 0; i < m_Size; i++)
            m_Data(i).~T();
        m_Size = 0;
    }
    
    size_t size() const {
        return m_Size;
    }
    
    size_t capacity() const {
        return m_Capacity;
    }
    
    bool empty() const {
        return m_Size == 0;
    }
    
    const T& operator()(size_t index) const {
        if (index >= m_Size)
            throw "Index out of bounds";
        
        return m_Data(index);
    }
    
    T& operator()(size_t index) {
        if (index >= m_Size)
            throw "Index out of bounds";
        
        return m_Data(index);
    }
    
    Vector<T> operator+(const Vector& other) {
        if (m_Size != other.size())
            throw "Vectors are of different size";
        
        Vector<T> v(m_Size);
        for (size_t i = 0; i < m_Size; i++) {
            v.push_back(m_Data(i) + other(i));
        }
        
        return v;
    }
    
};

template <
typename T,
typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
int norm(const Vector<T> v) {
    int nrm = 0;
    size_t n = v.size();
    
    for (int i = 0; i < n; i++) {
        nrm += v(i)*v(i);
    }
    
    return sqrt(nrm);
}

template <typename T>
std::ostream& operator<<(std::ostream& s, const Vector<T>& v) {
    s << "(";
    size_t n = v.size();
    for (size_t i = 0; i < n; i++) {
        s << v(i) << (i < n - 1 ? ", " : "");
    }
    s << ")";
    return s;
}

int main(int argc, const char * argv()) {
    Vector<int>* a = new Vector<int> {1, 2, 3, 4, 5};
    Vector<int> b = {5, 4, 3, 2, 6};
    Vector<int> c = b;

    return 0;
}

Thank you.