I am wiring my own std::vector implementation. I am getting assertion failure while iterating its elements. I tried copying my code from Visual Studio to Wandbox and there the error I am getting is: *** Error in `./prog.exe': double free or corruption (fasttop): 0x0000000000e95150 ***

#include <iostream>
#include <string>
#include <stdexcept>
#include <cmath>

using std::cin;
using std::cout;
using std::endl;

#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64 true
#else
#define ENVIRONMENT32 true
#endif
#endif

// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64 true
#else
#define ENVIRONMENT32 true
#endif
#endif

namespace dq {
    template <typename T>
    class vector {
    private:
        size_t sz;
        size_t cap;
        T *elem;
    public:
        // Member types
        typedef T * iterator;
        typedef const T * const_iterator;
        typedef T & reference;
        typedef const T & const_reference;
        // reverse iterator
        // const reverse iterator
        // pointer
        // const pointer
        // Member functions
        vector() : sz{ 0 }, elem{ new T[sz] }, cap{ 0 } {};
        vector(size_t sz) : sz{ sz }, elem{ new T[sz] }, cap{ sz } {};
        vector(size_t sz, T val) : sz{ sz }, elem{ new T[sz] }, cap{ sz } { std::fill_n(elem, sz, val); }
        vector(std::initializer_list<T> il)
            : sz{ static_cast<std::size_t>(il.size()) },
            cap{ sz },
            elem{ new T[il.size()] } {
            std::copy(il.begin(), il.end(), elem);
        }
        ~vector() { delete[] elem; }
        // operator =
        // assign
        // get_allocator
        // Element access
        reference operator[](int i) {
            if (i < 0 || i >= sz) throw std::out_of_range("element is out of range");
            return elem[i];
        }
        const_reference operator[](int i) const {
            if (i < 0 || i >= sz) throw std::out_of_range("element is out of range");
            return elem[i];
        }
        reference front() {
            if (sz == 0) throw std::out_of_range("empty vector");
            return elem[0];
        }
        reference back() {
            if (sz == 0) throw std::out_of_range("empty vector");
            return elem[sz - 1];
        }
        // data
        // Iterators
        iterator begin() {
            if (sz == 0) throw std::out_of_range("empty vector");
            return elem;
        }
        iterator end() {
            if (sz == 0) throw std::out_of_range("empty vector");
            return elem + sz;
        }
        // rbegin
        // rend
        // Capacity
        bool empty() { return sz == 0; }
        size_t size() const { return sz; }
        size_t capacity() const { return cap; }
        size_t max_size() {
            if (ENVIRONMENT64) return (pow(2, 64) / sizeof(T) - 1);
            return (pow(2, 32) / sizeof(T) - 1);
        }
        // reserve
        void shrink_to_fit() {
            if (sz == cap) return;
            T *resize = new T[sz];
            std::move(&elem[0], &elem[sz], resize);
            cap = sz;
            delete[] elem;
            elem = resize;
        }
        // Modifiers
        void clear() {
            sz = 0;
            delete[] elem;
            elem = new T[cap];
        }
        iterator insert(iterator it, const T & val) {
            if (it > elem + sz) throw std::out_of_range("out of range");
            if (sz == cap) resize(sz * 2);
            sz++;
            std::move(it, it + sz, it + 1);
            *(it) = val;
            return it;
        }
        iterator insert(iterator it, std::initializer_list<T> il) {
            if (it > elem + sz) throw std::out_of_range("out of range");
            size_t dist = il.size();
            if (sz + dist >= cap) resize((sz + dist) * 2);
            sz += dist;
            std::move(it, it + sz - dist, it + dist);
            std::move(il.begin(), il.end(), it);
            return it;
        }
        void erase(int i) {
            if (i < 0 || i >= sz) return;
            sz--;
            std::move(&elem[i + 1], &elem[sz], &elem[i]);
        }
        void push_back(T n) {
            if (sz == cap) resize(sz * 2);
            elem[sz] = n;
            sz++;
        }
        void push_front(T n) {
            if (sz == cap) resize(sz * 2);
            std::move(&elem[0], &elem[sz], &elem[1]);
            elem[0] = n;
            sz++;
        }
        void resize(size_t n) {
            size_t end;
            if (n == cap) return;
            T *resize = new T[n];
            if (n < sz) {
                sz = n;
                end = n;
            }
            else end = sz;
            std::move(&elem[0], &elem[end], resize);
            cap = n;
            delete[] elem;
            elem = resize;
        }
        void swap(vector<T> & vec) {
            size_t sw_sz = vec.sz;
            size_t sw_cap = vec.cap;
            vector<T> sw_c(vec.size());
            vector<T> sw_o(sz);
            std::move(vec.begin(), vec.end(), sw_c.elem);
            std::move(&elem[0], &elem[sz], sw_o.elem);
            vec.sz = sz;
            vec.cap = cap;
            delete[] vec.elem;
            delete[] elem;
            sz = sw_sz;
            cap = sw_cap;
            elem = sw_c.elem;
            vec.elem = sw_o.elem;
        }
        // void emplace_back();
        void pop_back() {
            cout << "e" << endl;
        }
        // void emplace();
        // Non-member functions
        friend std::ostream & operator << (std::ostream & out, dq::vector<T> a) {
            for (auto i : a)
                cout << i << " ";
            return out;
        }
    };
}

int main() {
    dq::vector<double> vec1{ 10, 20, 30, 40, 50 };

    cout << vec1 << endl;
    cout << vec1 << endl;

    cin.get();
    return 0;
}

Is this a problem with my implementation of iterators or I made a mistake by using wrong methods to access elements of vector?

0 Answers