Как удалить динамический массив c
Кроме отдельных динамических объектов в языке C++ мы можем использовать динамические массивы. Для выделения памяти под динамический массив также используется оператор new , после которого в квадратных скобках указывается, сколько массив будет содержать объектов:
int *numbers ; // динамический массив из 4 чисел // или так // int *numbers = new int[4];
Причем в этом случае оператор new также возвращает указатель на объект типа int — первый элемент в созданном массиве.
В данном случае определяется массив из четырех элементов типа int, но каждый из них имеет неопределенное значение. Однако мы также можем инициализировать массив значениями:
int *numbers1 >; // массив состоит из чисел 0, 0, 0, 0 int *numbers2 >; // массив состоит из чисел 1, 2, 3, 4 int *numbers3 >; // массив состоит из чисел 1, 2, 0, 0 // аналогичные определения массивов // int *numbers1 = new int[4]<>; // массив состоит из чисел 0, 0, 0, 0 // int *numbers1 = new int[4](); // массив состоит из чисел 0, 0, 0, 0 // int *numbers2 = new int[4]< 1, 2, 3, 4 >; // массив состоит из чисел 1, 2, 3, 4 // int *numbers3 = new int[4]< 1, 2 >; // массив состоит из чисел 1, 2, 0, 0
При инициализации массива конкретными значениями следует учитывать, что если значений в фигурных скобках больше чем длина массива, то оператор new потерпит неудачу и не сможет создать массив. Если переданных значений, наоборот, меньше, то элементы, для которых не предоставлены значения, инициализируются значением по умолчанию.
Стоит отметить, что в стандарт С++20 добавлена возможность выведения размера массива, поэтому, если применяется стандарт С++20, то можно не указывать длину массива:
int *numbers >; // массив состоит из чисел 1, 2, 3, 4
После создания динамического массива мы сможем с ним работать по полученному указателю, получать и изменять его элементы:
int *numbers >; // получение элементов через синтаксис массивов std::coutПричем для доступа к элементам динамического массива можно использовать как синтаксис массивов ( numbers[0] ), так и операцию разыменования ( *numbers )
Соответственно для перебора такого массива можно использовать различные способы:
unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout ; i < n; i++) < std::cout std::cout ; q != p + n; q++) < std::cout std::coutОбратите внимание, что для задания размера динамического массива мы можем применять обычную переменную, а не константу, как в случае со стандартными массивами.
Для удаления динамического массива и освобождения его памяти применяется специальная форма оператора delete :
delete [] указатель_на_динамический_массив;#include int main() < unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout
Чтобы после освобождения памяти указатель не хранил старый адрес, также рекомендуется обнулить его:
delete [] p; p = nullptr; // обнуляем указательМногомерные массивы
Также мы можем создавать многомерные динамические массивы. Рассмотрим на примере двухмерных массивов. Что такое по сути двухмерный массив? Это набор массив массивов. Соответственно, чтобы создать динамический двухмерный массив, нам надо создать общий динамический массив указателей, а затем его элементы - вложенные динамические массивы. В общем случае это выглядит так:
#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив // выделяем память для вложенных массивов for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // удаление массивов for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >Вначале выделяем память для массива указателей (условно таблицы):
int** numbers>;Затем в цикле выделяем память для каждого отдельного массива (условно строки таблицы):
numbers[i] = new int[columns]<>;Освобождение памяти идет в обратном порядке - сначала освобождаем память для каждого отдельного вложенного массива, а затем для всего массива указателей.
Пример с вводом и выводом данных двухмерного динамического массива:
#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // вводим данные для таблицы rows x columns for (unsigned i<>; i < rows; i++) < std::cout ; j < columns; j++) < std::cout > numbers[i][j]; > > // вывод данных for (unsigned i<>; i < rows; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < columns; j++) < std::cout std::cout for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >Пример работы программы:
Enter data for 1 row 1 column: 2 2 column: 3 Enter data for 2 row 1 column: 4 2 column: 5 Enter data for 3 row 1 column: 6 2 column: 7 2 3 4 5 6 7Указатель на массив
От типа int** , который представляет указатель на указатель (pointer-to-pointer) следует отличать ситуацию "указатель на массив" (pointer to array). Например:
#include int main() < unsigned n; // количество строк int (*a)[2] = new int[n][2]; int k<>; // устанавливаем значения for (unsigned i<>; i < n; i++) < // устанавливаем данные для столбцов i-й строки for (unsigned j<>; j < 2; j++) < a[i][j] = ++k; >> // вывод данных for (unsigned i<>; i < n; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < 2; j++) < std::cout std::cout // удаляем данные delete[] a; a = nullptr; >Здесь запись int (*a)[2] представляет указатель на массив из двух элементов типа int. Фактически мы можем работать с этим объектом как с двухмерным массивом (таблицей), только количество столбцов в данном случае фиксировано - 2. И память для такого массива выделяется один раз:
int (*a)[2] = new int[n][2];То есть в данном случае мы имеем дело с таблице из n строк и 2 столцов. Используя два индекса (для строки и столца), можно обращаться к определенному элементу, установить или получить его значение. Консольный вывод данной программы:
1 2 3 4 5 6C++. Правильное удаление динамического двумерного массива
Всем привет. Я новичок в программировании и только начинаю многое осваивать(хотя и имею кое-какую подготовку, но считать её хоть сколь-либо серьезной смешно). Знакомлюсь с классами, пытаясь соорудить нечто для работы с матрицами. Код реализации не важен, важно то, что получаю ошибку: 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#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 int Matrix::rows() < return m_rows; >int Matrix::cols() < return m_cols; >Matrix::~Matrix()int main()При пошаговой проверке в Visual Studio программа сыплется на удалении внешнего указателя delete[] m_matrix; Собственно, прошу помочь =)
Отслеживать
44.8k 3 3 золотых знака 38 38 серебряных знаков 89 89 бронзовых знаков
задан 10 фев 2017 в 13:08
43 1 1 золотой знак 1 1 серебряный знак 3 3 бронзовых знака
Было бы лучше, если бы вы добавили текст ошибки в вопрос не как ссылку
10 фев 2017 в 13:23
Буду иметь ввиду. Новичок на stackoverflow)
10 фев 2017 в 16:205 ответов 5
Сортировка: Сброс на вариант по умолчанию
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::~Matrix()C++ Динамический массив. Удаление элемента
P.S.
То, что ты написал - это не С++, а просто С.#3
16:05, 28 янв 2008Почему нет? Можно удалить элемент, потом вручную сдвинуть все элементы с удаленной позиции на единицу. Примерно это же и будет делать std::vector, но удалять из середины массива (вектора) есть вселенское зло.
#4
16:18, 28 янв 2008mirat
> Почему нет?
Потому, что исходный вопрос автора был "можно мне как-нибудь так хитро вызвать delete, чтобы массив сам сделал всё как надо ?"
И с этой позиции вариант
> Можно удалить элемент, потом вручную сдвинуть все элементы с удаленной позиции на единицу.
не катит.
Вот вектор - да, целостная сущность, обладающая нужным функционалом.#5
16:30, 28 янв 2008по поводу
стоимость операции удаления буде линейно зависить от кол-ва элементов?#6
16:59, 28 янв 2008HolyDel
Из середины да, из конца - константное время.Nikopol
Не телепат, не знаю, что автор имел в виду :)#7
17:03, 28 янв 2008Все понятно. Всем спасибо
#8
17:17, 28 янв 2008если удалять, то уж лучше std::list использовать.
#9
17:33, 28 янв 2008замечу только что если порядок элементов в массиве не важен то делать своп с последним элементом + pop_back => константное время удаления
- TaurenChief
- Постоялец
#10
17:42, 28 янв 2008
#11
17:52, 28 янв 2008
#12
18:24, 28 янв 2008
JokerR
>замечу только что если порядок элементов в массиве не важен то делать своп с последним элементом + pop_back => константное время удаления
Но размер вектора не уменьшится (резервированный в памяти)
#13
19:18, 28 янв 2008
О. Федор
А что должен? Он у вектора не уменьшится в любом случае, кроме хака со swap'ом
#14
19:21, 28 янв 2008
вообще-то это implementation-depended
Динамические массивы и переменные в C++: легко и просто!

Всем привет! В этой статье мы создадим массив и переменные применяя указатели. Если вы еще не почитали прошлую (начальную) статью про указатели, то советуем сначала изучить ее. Ну а если вы это все знаете, то погнали!
Что такое динамические переменные
Динамические переменные - это переменные, которые созданы напрямую с помощью указателей. Для них существует функция удаление (это мы разберем ниже).
Чтобы мы могли полноценно создавать динамические переменные, нам понадобится изучить конструктор - new , после его использования в оперативной памяти