#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]; Оказалось более чем достаточно.
Комментариев нет:
Отправить комментарий