#cpp #массивы #классы #указатели
Всем привет. Я новичок в программировании и только начинаю многое осваивать(хотя
и имею кое-какую подготовку, но считать её хоть сколь-либо серьезной смешно). Знакомлюсь
с классами, пытаясь соорудить нечто для работы с матрицами. Код реализации не важен,
важно то, что получаю ошибку:
http://prntscr.com/e6y5on
Ключевой вопрос в том, как её исправить.
Matrix.h:
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
private:
int m_rows = 1;
int m_cols = 1;
int** m_matrix = new int* [m_rows];
public:
Matrix(int rows, int cols);
void SetSize(int rows, int cols);
void Create();
int rows();
int cols();
~Matrix();
};
#endif
Matrix.cpp:
#include
#include
#include "matrix.h"
using namespace std;
Matrix::Matrix(int rows, int cols)
{
SetSize(rows, cols);
Create();
}
void Matrix::SetSize(int rows, int cols)
{
m_rows = rows;
m_cols = cols;
}
void Matrix::Create()
{
for (int i = 0; i < m_rows; i++)
m_matrix[i] = new int[m_cols];
cout << "Matrix created with " << m_rows << " rows and " << m_cols <<
" cols." << endl;
}
int Matrix::rows()
{
return m_rows;
}
int Matrix::cols()
{
return m_cols;
}
Matrix::~Matrix()
{
for (int i = 0; i < m_rows; i++)
delete[] m_matrix[i];
delete[] m_matrix;
cout << "Matrix deleted" << endl;
}
main.cpp:
int main()
{
Matrix m(2,2);
return 0;
}
При пошаговой проверке в Visual Studio программа сыплется на удалении внешнего указателя
delete[] m_matrix;
Собственно, прошу помочь =)
Ответы
Ответ 1
Давайте разбираться. int m_rows = 1; int m_cols = 1; int** m_matrix = new int* [m_rows]; Итак, у вас сразу выделяется память и создается матрица 1x1. Поскольку в конструкторе Matrix::Matrix(int rows, int cols) у вас нет инициализации членов, они инициализированы по умолчанию этой матрицей. Но что вы делаете дальше? Вы переписываете m_rows и m_cols, и в уже выделенный массив для ОДНОГО указателя записываете их m_rows, т.е. в данном конкретном случае - два. Вот вам и источник ваших неприятностей. Ваша попытка исправить ситуацию - это просто попытка не заметить ошибку. Ни к чему хорошему привести это не может. В следующий раз вы запишете туда их с десяток, и таки засорите память основательнее, только и всего. Вот как по-хорошему должна выглядеть ваша матрица: class Matrix { private: int m_rows; int m_cols; int** m_matrix; public: Matrix(int rows, int cols); void SetSize(int rows, int cols); void Create(); int rows(); int cols(); ~Matrix(); }; Matrix::Matrix(int rows, int cols) :m_rows(rows),m_cols(cols) { m_matrix = new int*[m_rows]; for (int i = 0; i < m_rows; i++) m_matrix[i] = new int[m_cols]; cout << "Matrix created with " << m_rows << " rows and " << m_cols << " cols." << endl; } Matrix::~Matrix() { for (int i = 0; i < m_rows; i++) delete[] m_matrix[i]; delete[] m_matrix; cout << "Matrix deleted" << endl; }Ответ 2
Судя по всему вы создаёте int** m_matrix размером один, а потом передаёте параметр 2 и думаете что там 2 строки. Видимо вам лучше создавать динамичкский массив в методе Create: void Matrix::Create(){ m_matrix = new int*[m_rows]; for (int i = 0; i < m_rows; i++) m_matrix[i] = new int[m_cols]; cout << "Matrix created with " <Ответ 3
В классе имеется обращение за пределы выделенной памяти. Если вы добавите следуюшие два предложения в конструктор Matrix::Matrix(int rows, int cols) { std::cout << "m_rows = " << m_rows << std::endl; std::cout << "m_cols = " << m_cols << std::endl; SetSize(rows, cols); Create(); } то при создании объекта класса на консоль будет выдано сообщение m_rows = 1 m_cols = 1 Это означает, что перед тем. как тело конструктора получило управление, была выполнена инициализация членов класса int m_rows = 1; int m_cols = 1; int** m_matrix = new int* [m_rows]; в результате которой была выделена память для массива указателей из одного указателя типа int *. Однако в функции Create, так как в общем случае значение m_rows, заданное в конструкторе, может отличаться от 1, то происходит выход за пределы динамически выделенного массива. void Matrix::Create() { for (int i = 0; i < m_rows; i++) m_matrix[i] = new int[m_cols]; cout << "Matrix created with " << m_rows << " rows and " << m_cols << " cols." << endl; } Нет никакого смысла инициализировать члены класса в определении класса вместо того, чтобы инициализировать их в конструкторе. Имейте в виду, что вам необходимо также определить конструктор копирования и копирующий оператор присваивания, или определить их как удаленные.Ответ 4
Вы неправильно выделяете память. Эту строку: int** m_matrix = new int*[m_rows]; необходимо перенести из заголовка (.h) в реализацию функции Create(): void Matrix::Create() { m_matrix = new int*[m_rows]; for (int i = 0; i < m_rows; i++) m_matrix[i] = new int[m_cols]; } В заголовке оставляете только объявление указателя: int** m_matrix; Деструктор возвращаете к вашему первоначальному виду: Matrix::~Matrix() { for (int i = 0; i < m_rows; i++) delete[] m_matrix[i]; delete[] m_matrix; }Ответ 5
Нашёл ответ на собственный вопрос. Не знаю дело ли в классе или же это так правильно, но удаления for (int i = 0; i < m_rows; i++) delete[] m_matrix[i]; Оказалось более чем достаточно.
Комментариев нет:
Отправить комментарий