![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
bsa |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Так как язык С++ добавляет свои средства работы с массивами к имеющимся в языке Си, то рассмотрим сначала то, чем располагает Си, а затем уже то, что привносит С++.
Динамические массивы в Си Массив - это набор однотипных данных, доступ к которым может быть осуществлен по индексу, т.е. по номеру элемента. В Си принято нумеровать элементы с нуля, поэтому первый элемент всегда имеет индекс 0, а последний - (N-1), где N - это размер массива (количество элементов). Встроенные средства языка программирования Си позволяют создавать статические массивы - массивы, число элементов которых задается на этапе компиляции и в процессе работы программы не меняется. Но как только сложность задач выходит за банальное "Hello, world!", возникает необходимость менять размеры массива в процессе работы программы... Что представляет собой массив на уровне ЭВМ? Это непрерывный кусок памяти, в который помещаются все элементы массива. Таким образом, для изменения количества элементов в массиве нужно менять размер этого куска. Но для начала его нужно выделить... Последняя версия стандарта языка Си позволяет создавать автоматические динамические массивы. Они существуют только в пределах текущей области видимости и при выходе из нее уничтожаются. Синтаксис записи аналогичен статическим массивам, только в качестве указателя размера выступает не числовая константа, а переменная:
Стандартная библиотека Си предоставляет средства для работы с динамической памятью, такие как: malloc, calloc - выделение памяти free - освобождение памяти realloc - изменение размера выделенной области памяти (может замещать собой и malloc, и free) Для их использования надо подключить заголовочный файл stdlib.h:
Функция calloc() производит выделение памяти под набор элементов одинакого размера и его зануление. Первым параметром указывается количество необходимых элементов, а вторым размер элемента в байтах:
Функция realloc() позволяет изменять размер области памяти, которая выделена функциями realloc(), malloc() или calloc() (на самом деле, она еще может выделять память, как malloc, и освобождать, как free):
Вот пример использования динамического массива:
Как нетрудно заметить, в конце функции идет освобождение памяти, выделенной под массив. Чтобы избежать утечек памяти, нужно всегда освобождать память, как только она перестала быть нужной. Динамические массивы нельзя копировать путем присваивания указателей:
Стоит иметь в виду, что указатели на внутренние элементы динамического массива использовать не очень безопасно. Так как после очередного изменения размера массива они могут стать неверны, что приведет к возникновению трудно отслеживаемых ошибок. Указатели на внутренние элементы стоит применять только там, где не предполагается изменений размеров массива. Создать полностью динамический многомерный массив стандартными средствами языка Си невозможно (как создать частично динамический массив будет сказано ниже). Но можно сымитировать одним из двух способов: 1. через массив массивов 2. через одномерный массив Рассмотрим первый вариант реализации многомерных динамических массивов на примере двумерного. Для этого создадим указатель на указатель на, например, int:
Для второго способа нужно создать одномерный массив, число элементов которого равно произведению всех размерностей:
Как вариант можно создать многомерный массив, у которого только одна размерность динамическая, при этом скорость работы с ним аналогична статическому массиву (это не относится ко времени выделения памяти). Динамической может быть только первая размерность (например, для двумерного массива это количество строк). Для этого надо создать указатель на массив, размерность которого на один меньше необходимой (например, чтобы получить динамический двумерный массив, нужно создать указатель на одномерный массив с нужным числом столбцов). Например:
После определения указателя нужно выделить под массив память (далее для простоты рассматривается двумерный массив):
--------------------------------------------------------------------------------------------------------------------- Динамические массивы в Си++ Массив - это набор однотипных данных, доступ к которым может быть осуществлен по индексу, т.е. по номеру элемента. В Си++, так же как и вв Си, принято нумеровать элементы с нуля, поэтому первый элемент всегда имеет индекс 0, а последний - (N-1), где N - это размер массива (количество элементов). Средства языка программирования Си++ позволяют создавать статические массивы - массивы, число элементов которых задается на этапе компиляции и в процессе работы программы не меняется. Но как только сложность задач выходит за банальное "Hello, world!", возникает необходимость менять размеры массива в процессе работы программы... Что представляет собой массив на уровне ЭВМ? Это непрерывный кусок памяти, в который помещаются все элементы массива. Таким образом, для изменения количества элементов в массиве нужно менять размер области памяти. В языке С++ есть встроенные средства, для работы с динамической памятью - new[] и delete[], позволяющие выделять память под массивы и освобождать ее. Чтобы выделить память с помощью new нужно указать тип элемента массива после ключевого слова new и их количество в квадратных скобках. Чтобы освободить память, занимаемую выделенным таким образом массивом необходимо вызвать delete[]. В отличие от free(), delete[] может принимать в качестве аргумента и нулевой указатель, в этом случае он ничего не сделает. Пример:
Так как vector это шаблон, то нужно указать тип объекта, которые будут храниться в массиве. Это делается с помощью угловых скобок: std::vector<int>. Вот небольшой пример использования шаблона vector:
Создать полностью динамический многомерный массив стандартными средствами языка Си++ невозможно (как создать частично динамический массив будет сказано ниже). Но можно сымитировать одним из двух способов: 1. через массив массивов 2. через одномерный массив Рассмотрим первый вариант реализации многомерных динамических массивов на примере двумерного:
Для второго способа нужно создать одномерный массив, число элементов которого равно произведению всех размерностей:
Можно совместить два этих способа:
Как вариант можно создать многомерный массив, у которого только одна размерность динамическая, при этом скорость работы с ним аналогична статическому массиву. Динамической может быть только первая размерность (например, для двумерного массива это количество строк). Для этого надо создать указатель на массив, размерность которого на один меньше необходимой (например, чтобы получить динамический двумерный массив, нужно создать указатель на одномерный массив с нужным числом столбцов). Например:
После определения указателя нужно выделить под массив память (далее для простоты рассматривается двумерный массив):
Назад к FAQ Это сообщение отредактировал(а) bsa - 26.7.2011, 11:01 |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
bsa, а где-же new/delete?
![]() Ещё, прошу добавить ссылки: 1. На википедию(массив) 2. На cppreference.com или куда-нибудь ещё(malloc, free, realloc и т.д.) -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
Damarus |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Awaiting Authorisation Сообщений: 671 Регистрация: 6.5.2006 Репутация: нет Всего: 29 |
bsa, можно ещё написать про многомерные динамические массивы.
|
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
Damarus, согласен - а я проглядел
![]() -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
Shaggie |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 570 Регистрация: 21.12.2006 Где: outer space Репутация: нет Всего: 72 |
Скорее всего, на момент чтения ФАКа информация для читающего будет очень новая и неизвестная. Поэтому следующие моменты немножко напрягли:
И без объяснений... Я бы порекомендовал, во-первых, вкратце описать использование шаблонов в объявлении вектора (хотя бы так - "динамический массив должен содержать примитивы или объекты определённого типа, который мы указываем вот таким способом"), и, во-вторых, описать итератор как специальный тип указателя, используемый для перебора элементов в сложных коллекциях. |
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
Внимательно прочитал статью. Всё отлично. Есть только одно замечание.
Зависит от того, что именно понимать под многомерным дин. массивом. Есть способ динамически создать многомерный массив у которого только лишь одна из размерностей будет переменной. В статье этот момент нужно проговорить(возможно, привести пример). -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
archimed7592, ты имеешь в виду что-то типа:
Так что этот пункт прошу проверить отдельно и с пристрастием. |
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
Да. На С++ это будет выглядеть так:
Теория тут следующая: 1. Скорость доступа [почти] такая же как у статических массивов. 2. Скорость создания такая же, как у одномерного динамического массива. 3. arr[i][j][k] == *((int *)arr + (i * 5 + j) * 6 + k) (могу ошибаться, но вроде так) - компилятор сам делает эти вычисления(как и со статическими массивами). 4. При создании такого массива, динамической может быть только первая(крайняя левая) размерность(остальные константы). На самом деле обо всём этом писать не обязательно(на твоё усмотрение). Я лишь хотел бы, чтобы либо не было фразы "создать динамический многомерный массив средствами языка невозможно", либо эта фраза была уточнена в виду упомянутого способа. Это сообщение отредактировал(а) archimed7592 - 3.1.2008, 14:37 -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
Лучше показать, что эта величина может быть переменной(к примеру, считать её из потока стандартного ввода). -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 6 Всего: 162 |
Извиняюсь за занудность, но я же назначался вычитщиком?
![]() Массив - это набор а последний - (N-1) таким образом, для достаточно для организации Разве что, sizeof(p) ... И, чтобы избежать утечек памяти, нужно
... не происходило, нужно ... запятая не нужна сЫмитировать У меня всё, сама статья понравилась. Добавлено через 2 минуты и 43 секунды P.S. а кто главред? |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 4 Всего: 459 |
Хотелось бы еще про динамические строки, как частный случай массивов переменной длинны.
Напрашивается ГлавВред ![]() -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
Ты ![]()
Только если отдельной статьёй, а то слишком много получится(разве о них не написано в прикреплённой теме "указатели, строки, классы"?) -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
bsa |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Не. Разве что разместить ссылку на статью про строки, как частный вариант массивов. Но не более того. А то мне уже самому страшно смотреть на то, что получилось - ОЧЕНЬ МНОГО! Добавлено @ 17:16
archimed7592: Оффтоп про alloca перенесён в отдельную тему. Это сообщение отредактировал(а) archimed7592 - 10.1.2008, 23:51 |
||||
|
|||||
Fazil6 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 7 Всего: 60 |
хм... почему это? Вообще тема new/delete нераскрыта... Лучше статья будет читаться, если разбить ее хотябы на подразделы с собственными подзаголовками причем раз уж пытаешься объять необъятное, то четко разделить C и С++, а вообще как и раньше мои претензии по объему. Опять же я, например, так и не понял почему рассмотрение началось с функции realloc , а не calloc и резонный вопрос почему для выделения памяти существуют 2 функции Это сообщение отредактировал(а) Fazil6 - 3.1.2008, 17:49 |
|||
|
||||
archimed7592 |
|
||||||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 6 Всего: 93 |
Ты уверен, что это эквивалентно? ;) Могу заблуждаться, но, IIRC, помимо всего прочего, calloc инициализирует выделенную область памяти нулями.
У меня будет маленькая просьба, относительно realloc: либо из статьи вообще убрать упоминания(как в тексте, так и в коде) о том, что с помощью realloc можно и выделять и освобождать память, либо вынести это в примечание. Для этого есть несколько причин: 1. Информация "излишняя" т.е., воспользовавшись этой информацией, новичек не сможет сделать ничего такого чего он не мог бы сделать с помощью malloc+free. 2. Использовать realloc как универсальную ф-цию нужно в достаточно редких случаях и отличить эти случаи от тех, где надо бы воспользоваться malloc+free сможет не каждый новичек, а, как следствие, статья некоторых новичков статья научит плохому стилю, чего хотелось бы не допускать. И ещё одна просьба: насколько я понял ты отделил Си от С++(я чесслово уже не помню как было прежде). Дык вот, информация о многомерных массивах осталась в "смешанном" виде - нужно разделить. Потом посмотрим, но учти, что, скорее всего, будем делить на две статьи(одна для Си, другая для плюс-плюс). Добавлено @ 22:53 Кстати, если про calloc не заблуждаюсь, то неплохо было бы об этом написать.
Это сообщение отредактировал(а) archimed7592 - 10.1.2008, 23:55 -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
||||||
|
|||||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |