![]() |
|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
![]() |
|
Опции темы | Поиск в этой теме |
![]() |
#1 |
Пользователь
Регистрация: 11.05.2019
Сообщений: 21
|
![]()
Как известно объявление массива требует определить границы, например, int array[n], где n - целочисленное значение.
Однако что делать, если требуется указать размер массива в функции, а само значение n будет поступать из стандартного ввода? Например, Код:
Код:
|
![]() |
![]() |
![]() |
#2 |
Старожил
Регистрация: 15.02.2010
Сообщений: 15,821
|
![]()
int p[]
int* p std::vector& p ... |
![]() |
![]() |
![]() |
#3 |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
![]() |
![]() |
![]() |
![]() |
#4 |
Заблокирован
Регистрация: 17.12.2018
Сообщений: 514
|
![]() |
![]() |
![]() |
![]() |
#5 |
Заблокирован
Регистрация: 17.12.2018
Сообщений: 514
|
![]()
Костя, массивы есть: константные, статические, динамические, разреженные, логические и физические. Константным называется массив, у которого не только количество элементов – известная на этапе разработки константа, которой нельзя ничего присвоить, но и сами элементы – константы. И сам массив – одна большая не скалярная константа. Пример:
Код:
Статическим называется массив, элементы которого могут менять свои значения, но из количество – константа. Такой массив может быть размещён и на стеке, это не то же самое, что Код:
Последний раз редактировалось taras-proger77; 08.06.2019 в 11:11. |
![]() |
![]() |
![]() |
#6 |
Заблокирован
Регистрация: 17.12.2018
Сообщений: 514
|
![]()
Статический и физический массивы могут быть зарезервированными. Зарезервированный массив – это массив такого размера, которого должно хватить, когда не известно, какого размера массив нужен. Если в разреженном массиве нужны только нулевой и пятимиллиардный элементы и не допускаются отрицательные индексы и индексы больше пяти миллиардов, то логический массив состоит из пяти миллиардов одного элемента, а физический – не менее, чем из двух элементов. Константный массив целесообразно делать статической величиной, а статический часто является как раз автоматической переменной. Статические у него тип переменной и размер, а не тип памяти.
|
![]() |
![]() |
![]() |
#7 |
Вредный кошак
Участник клуба
Регистрация: 14.10.2012
Сообщений: 1,159
|
![]()
Не претендуя на полноту.
Код:
Ну что же, можно познакомиться и с динамическим выделением памяти. Итак, если Вашему приложению понадобилась динамическая память, то можно запросить себе еще некоторое количество памяти во время выполнения. При этом нужно внимательно следить за тем, чтобы не произошло утечки памяти. Дело в том, что то, что мы выделили динамически, мы должны сами же и освободить, когда оно нам больше не нужно. В C для выделения памяти есть функции malloc, calloc, realloc, но это в C. Эти функции ничего не знают о устройстве C++ и просто выделяют (точнее, просят у системы) "сырой" непрерывный кусок памяти заданного размера (в байтах), и возвращают при этом указатель на "нечто" (void*). Причем, если память выделить не удалось, то вернется "NULL". Для освобождения памяти используется функция free, она также ничего не знает о C++. В C++ для выделения такой же "сырой" памяти имеется operator new (и operator new[]). Отличие operator new от operator new[] - фактически в том, что можно более эффективнее реализовать собственные версии этих операторов. Так что всё, что сказано про operator new, относится и к operator new[]. Конечно, если где-то есть разница, я укажу. operator new так же запрашивает непрерывный кусок памяти, и возвращает указатель на "нечто" (void*). Никакие конструкторы эта штуковина тоже не вызывает, но уже знает о исключениях и если выделение зафейлится, то, кинет исключение, а не вернет nullptr. На самом деле, сначала еще попытает счастье с new_handler, но мы опустим этот момент. Также есть версия, которая не кидает исключение, а возвращает nullptr в случае неудачи и версия, которая совсем не выделяет память, а просто параметр-указатель проходит там "транзитом", причем можно еще и перегружать operator new, но сейчас не об этом. Для освобождения памяти, выделенной с помощью operator new используется operator delete. Для освобождения памяти, выделенной с помощью operator new[] используется operator delete[]. В C++ чаще для выделения памяти используется new-expression (не путать с operator new ). Имеются две версии new-expression - new и new[]. Первая версия выделяет количество памяти, достаточное для хранения одного элемента заданного типа и применяет соответствующий тип инициализации, например, вызывает конструктор без параметров. Вторая версия выделяет количество памяти, достаточное для хранения переданного количества элементов заданного типа и применяет соответствующий тип инициализации, например, вызывает конструкторы без параметров. new-expression фактически работает в два этапа: 1) Запрашивает память, вызывая operator new (вторая версия вызывает operator new[]), причем количество байт рассчитывает самостоятельно, основываясь на размере типа и количестве необходимых элементов (для первой версии это один элемент). Плюс может приписать некоторое количество байт для собственных нужд, например, для хранения количества элементов под которые выделена память. 2) Затем производит инициализацию элемента (вторая версия производит инициализацию всех элементов). Если инициализатор не указан, то будет использована default-initialization, если указан - direct-initialization. Ситуацию, когда при инициализации вылетает исключение пока не будем рассматривать. Если из new-expression не вылетит исключение, то вернется указатель на выделенный кусок памяти, либо будет возвращен nullptr, если была использована версия operator new, которая не выкидывает исключение в случае неудачи. Для освобождения памяти, выделенной с помощью new-expression, используется delete-expression. delete-expression также имеет две версии: delete и delete[] Соответственно, для освобождения памяти, выделенной с помощью new используется delete, а для памяти, выделенной с помощью new[] - delete[] delete-expression фактически, также работает в два этапа: 1) Вызывает деструктор объекта (delete[] вызывает деструкторы объектов). 2) Освобождает память, вызывая operator delete (delete[] вызывает operator delete[]). Пока мы не освободим память, она так и будет считаться занятой. Важно! Если мы потеряем последний указатель на выделенную память, и более никак не сможем добраться до адреса, который вернула соответствующая функция выделения, то, соответственно, мы не сможем освободить эту память и она так и будет висеть занятой до самого конца работы приложения. То есть память эту мы не сможем использовать (т.к. у нас нет её адреса), но при этом она будет помечена как "занятая", т.е. будет бесполезная трата памяти. Такая ситуация называется "утечка памяти". И за этими утечками не так просто уследить, если использовать "голые" указатели. |
![]() |
![]() |
![]() |
#8 |
Вредный кошак
Участник клуба
Регистрация: 14.10.2012
Сообщений: 1,159
|
![]()
И в одно сообщение всё не уместилось, так что продолжим.
Напишем несколько примеров и посмотрим на результат: Код:
Как видим, память выделилась, но конструкторы не вызывались. operator new тоже ничего не будет вызывать, а также выделит кусок памяти, поэтому пропустим его, перейдем сразу к new-expression: Код:
как видим, помимо того, что произошло выделение памяти, также вызвались конструкторы объектов, а при уничтожении вызвались деструкторы. Код:
В этом примере показано как можно "расширить" выделенный кусок памяти. Конечно, выделять память и копировать элементы при каждом чихе не очень эффективно, но это лишь пример. Например, std::vector работает по такому же принципу, только там память выделяется сразу с запасом и используется placement new для создания элементов (конечно, всё немного сложнее и вся эта фигня завернута в аллокатор). если нужно, могу подробнее описать, но не думаю, что на данном этапе обучения это будет очень понятно, собственно, поэтому и в этом посте содержатся некоторые допущения, и нет сложных примеров, а также placement new, перегрузок операторов new/delete и т.д. |
![]() |
![]() |
![]() |
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Объявление массива | angol89 | Microsoft Office Word | 1 | 29.03.2016 16:50 |
Объявление массива СИ | TotEnot | Общие вопросы C/C++ | 4 | 06.10.2015 00:42 |
Странное объявление массива | Smitt&Wesson | Общие вопросы C/C++ | 7 | 06.02.2015 17:54 |
объявление массива в VBA | Cannibal | Помощь студентам | 0 | 14.04.2011 08:23 |
объявление массива | Crasty | Помощь студентам | 7 | 05.11.2008 17:18 |