Ошибка при вызове деструктора

175
24 октября 2018, 11:00

помогите разобраться с проблемой, она довольно распространенная и на форуме куча сообщений про это но в моей программе я никак не могу найти где я ошибся, нужен ваш взгляд со стороны. Вот код:

#pragma once
#include <cstring>
class vec
{
public:
    vec()
    {
        m_size = offset;
        m_len = 0;
        m_vector = new int[m_size];
        memset(m_vector, 0, sizeof(m_vector));
    }
    vec(size_t size)
    {
        m_size = size;
        m_len = 0;
        m_vector = new int[m_size];
        memset(m_vector, 0, sizeof(m_vector));
    }
    vec(const vec& orig)
        :
        m_size(orig.m_size),
        m_len(orig.m_len),
        m_vector(nullptr)
    {
        m_vector = new int[m_size];
        for (size_t i = 0; i < m_len; ++i)
        {
            m_vector[i] = orig.m_vector[i];
        }
    }
    ~vec()
    {
        if (m_vector != nullptr)
        {
            delete[] m_vector;
            m_vector = nullptr;
        }
    }
    size_t GetSize()
    {
        return m_size;
    }
    size_t GetLength()
    {
        return m_len;
    }
    int* GetValue()
    {
        return m_vector;
    }
    vec& operator= (const vec& rhs)
    {
        if (m_vector)
        {
            delete[] m_vector;
            m_vector = nullptr;
            m_len = rhs.m_len;
            m_vector = new int[m_size];
            for (size_t i = 0; i < m_len; ++i)
            {
                m_vector[i] = rhs.m_vector[i];
            }
        }
        return *this;
    }
    int& operator[] (size_t index)
    {
        return m_vector[index];
    }
    bool operator== (const vec& rhs)
    {
        if (m_len != rhs.m_len)
            return false;
        for (unsigned int i = 0; i < m_len; ++i)
        {
            if (m_vector[i] != rhs.m_vector[i])
                return false;
        }
        return true;
    }
    bool operator!= (const vec& rhs)
    {
        if (!(this == &rhs))
            return true;
        return false;
    }
    void push_back(int value)
    {
        if (m_len == m_size)
        {
            vec v = vec(m_size * (m_size / 2));
            v = *this;
            this->m_size = v.m_size;
            *this = v;
        }
        m_vector[m_len] = value;
        m_len++;
    }
    void erase(unsigned int pos)
    {
        m_vector[pos] = m_vector[m_len - 1];
        --m_len;
    }
    void erase(unsigned int begin, unsigned int end)
    {
        for (unsigned int i = begin; i <= end; ++i)
        {
            m_vector[i] = m_vector[m_len - i - 1];
        }
        m_len -= end - begin;
    }
    void pop_back()
    {
        m_vector[m_len - 1] = 0;
        --m_len;
    }
private:
    static constexpr size_t offset = 8;
    size_t m_size;
    size_t m_len;
    int* m_vector;
};
#include "Vec.h"
int main()
{
    vec v0;
    v0.push_back(2);
    v0.push_back(22);
    v0.push_back(234);
    v0.push_back(2325);
    printf("\n");
    for (unsigned int i = 0; i < v0.GetLength(); ++i)
    {
        printf("%d ", v0[i]);
    }
    vec v1(v0);
    v1.push_back(532);
    v1.push_back(2324);
    v1.push_back(1321);
    v1.push_back(6532);
    v1.push_back(42);
    printf("\n");
    for (unsigned int i = 0; i < v1.GetLength(); ++i)
    {
        printf("%d ", v1[i]);
    }
    vec v2;
    v2 = v1;
    v2.push_back(456);
    v2.push_back(452);
    v2.push_back(224);
    v2.push_back(12);
    v2.push_back(698);
    v2.erase(4, 7);
    v2.pop_back();
    printf("\n");
    for (unsigned int i = 0; i < v2.GetLength(); ++i)
    {
        printf("%d ", v2[i]);
    }
    std::cin.get();
    return 0;
}
Answer 1

Оператор присваивания

vec& operator= (const vec& rhs)
{
    // 1. нет проверки на присваивание самому себе
    if (m_vector)
    // 2. что это за проверка??
    // т.е. если текущий вектор пустой - то присваивать не будем?
    {
        // если беспокоетесь за удаление нулевого указателя -
        // не бойтесь delete не сломается (ему можно передавать нулевые указатели)
        delete[] m_vector;
        m_vector = nullptr; // это лишнее
        m_len = rhs.m_len;
        m_vector = new int[m_size]; // интересный момент
        // выделение новой памяти под такой же размер что и был ранее?
        for (size_t i = 0; i < m_len; ++i)
        // т.е. если размер текущего массива был меньше чем количество элементов
        // массива-аргумента тут будет выход за границы
        {
            m_vector[i] = rhs.m_vector[i];
        }
    }
    return *this;
}

Учитывая все замечания можно написать следующий оператор присваивания:

vec& operator= (const vec& rhs)
{
    if (&rhs == this) return *this; // проверка на присваивание себе
    int new_size = rhs.m_size; // новый размер этого (this) массива
    int new_len = rhs.m_len;   // новая длина массива
    int* new_vector = new int[new_size]; // новый массив
    for (size_t i = 0; i < new_len; ++i) // копируем все данный в новый массив
        new_vector[i] = rhs.m_vector[i];
    // теперь уверенно удаляем старый массив
    delete[] m_vector;
    m_vector = new_vector; // запоминаем новый вектор
    // и запонимаем новые размеры
    m_size = new_size;
    m_len = new_len;
    return *this;
}

Функция вставки элемента в конец массива

void push_back(int value)
{
    if (m_len == m_size)
    {
        // новый размер вычисляется странным образом
        // т.е. если массив имеет размер 10000
        // ему вычислится следующий размер 5000 * 10000 = 50000000
        // многовато
        // популярные реализации векторов используют старый размер * 1,5 или на 2
        vec v = vec(m_size * (m_size / 2));
        // тут вобще магический подход
        v = *this;
        this->m_size = v.m_size;
        *this = v;
    }
    m_vector[m_len] = value;
    m_len++;
}

Работающий push_back будет выглядеть примерно следующим образом:

void push_back(int value)
{
    if (m_len == m_size)
    {
        int new_size = m_size * 1.5;    // вычисляем новый размер
        int* new_vector = new int[new_size]; // выделяем память под новый массив
        for (int i = 0; i < m_len; ++i) // копируем данные из текущего массива в новый
        {
            new_vector[i] = m_vector[i];
        }
        delete[] m_vector; // теперь удаляем старый массив
        m_vector = new_vector; // запоминаем наш новый массив
        m_size = new_size; // запоминаем новый размер
    }
    m_vector[m_len] = value;
    m_len++;
}
READ ALSO
sqlite3_open не получаетсяоткрыть базу в явно указанной директории

sqlite3_open не получаетсяоткрыть базу в явно указанной директории

ОС - Windows Кодировка входной строки - неизвестна, но скорее всего виндовская будетКодировка файлов проекта - набор символов юникода

199
EntityManager persist() не сохраняет данные в БД ( PostgreSQL )

EntityManager persist() не сохраняет данные в БД ( PostgreSQL )

При нажатии на кнопку Register должен добавляться новый пользователь в БДКонсоль выдает :

176
Package is declared in module, which is not in the module graph

Package is declared in module, which is not in the module graph

Сегодня запустил свой проект, обновил Intellij IDEA и произошло нечто такое, из-за чего я не могу писать свой прекрасный код

302
Как правильно собрать Maybe RxJava2?

Как правильно собрать Maybe RxJava2?

Работаю с Room есть вот такой метод

159