Разрушение матрицы C ++ вызывает точку останова и критическую ошибку - PullRequest
0 голосов
/ 24 февраля 2020

Итак, я хочу создать матричный класс 4x4, который хранит свои данные как float** m. Я инициализирую это так:

Matrix4f::Matrix4f()
{
    this->m = new float*[4];

    for (int i = 0; i < 4; i++)
    {
        this->m[i] = new float[4];
        memset(this->m[i], 0, sizeof(float) * 4);
    }
}

И после этого у меня есть такой деструктор:

Matrix4f::~Matrix4f()
{
    for (int i = 0; i < 4; i++)
    {
        delete[] m[i];
    }

    delete[] m;
}

Но иногда, когда я использую этот класс, эта строка:

delete[] m[i];

Вызывает точку останова и выдает: Critical error detected c0000374 Это правильный способ инициализации и удаления матрицы 4x4?

Ответы [ 2 ]

1 голос
/ 24 февраля 2020

Как указано в комментариях, ваш код в порядке, если и только если вы правильно управляете делом копий.

У вас есть три варианта:

  1. отключить копирование
  2. мелкая копия
  3. глубокая копия

Давайте обсудим этот выбор:

  1. вам нужно будет только объявить конструктор копирования и исключить оператор назначения копирования. Теперь нет возможности копировать объекты вашего класса. Это уменьшает полезность класса матрицы.

  2. Это не имеет реального значения для его собственного. Поскольку этого можно достичь, обернув объект типа 3 в std::shared_ptr.

  3. В этом случае не требуется динамическая c память. И даже если бы они были, вы бы хотели использовать std :: vector или что-то еще для управления памятью. Разумным решением было бы использовать float[4][4] как m. Это было бы более надежным, так как вы избежали управления памятью.

0 голосов
/ 24 февраля 2020

Как уже упоминалось, проблема может заключаться в правиле трех. Предоставленный вами код является технически правильным, однако, если вы копируете Matrix4f, вам нужно переопределить конструктор копирования и перегруженный конструктор присваивания:

#include <iostream>


class Matrix4f
{
public:
    Matrix4f()
        : m_data(new float*[4])
    {
        for (int i = 0; i < 4; i++)
            m_data[i] = new float[4]{ 0 };
    }
    Matrix4f(const Matrix4f& source)
    {
        m_data = new float*[4];
        for (int i = 0; i < 4; i++)
        {
            m_data[i] = new float[4]{ 0 };
            for (int j = 0; j < 4; j++)
            {
                m_data[i][j] = source.m_data[i][j];
            }
        }
    }
    Matrix4f& operator=(const Matrix4f& source)
    {
        if (this == &source) return *this;

        clear();
        m_data = new float*[4];
        for (int i = 0; i < 4; i++)
        {
            m_data[i] = new float[4]{ 0 };
            for (int j = 0; j < 4; j++)
            {
                m_data[i][j] = source.m_data[i][j];
            }
        }

        return *this;
    }
    ~Matrix4f()
    {
        clear();
    }
//private:
    float**m_data;

    void clear()
    {
        if (m_data != NULL)
        {
            for (int i = 0; i < 4; i++)
            {
                delete[] m_data[i];
            }
            delete[]m_data;
        }
    }

    void print()const
    {
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                std::cout << m_data[i][j] << "\t";
            }
            std::cout << "\n";
        }
    }
};



int main()
{
    Matrix4f m1;

    m1.m_data[0][0] = m1.m_data[1][1] = m1.m_data[2][2] = m1.m_data[3][3]  = 1;

    {
        Matrix4f m2(m1);
        Matrix4f m3 = m2;

        m2.print();
        m3.print();
    }

    m1.print();
}

Но я рекомендую вместо этого использовать одномерные векторы, это намного быстрее и намного безопаснее.

...