Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/26: Рейтинг темы: голосов - 26, средняя оценка - 4.54
 Аватар для Lindemann66
4 / 4 / 5
Регистрация: 28.04.2010
Сообщений: 162

Отличие операции с выделением памяти и без

09.08.2011, 16:05. Показов 6146. Ответов 60
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!

Не сочтите за глупость, но возник интересный вопрос, над которым давно думаю, а овтета нигде не находил

Вот нужно, допустим, создать массив из n элементов

Сделать это можно 2-мя способами


C++
1
int arr[n];

и
C++
1
int *arr = new int[n];
Но в одном случае создание массива сопровождается выделением памяти, а в другом - без
В чём принципиальная разница?
Я понимаю, в Qt сразу написано - объекты QObject необходимо создавать с выделением памяти, чтобы не было проблем
Понятно, так и делаем. А тут как правильней?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.08.2011, 16:05
Ответы с готовыми решениями:

Стек, куча, хранение в памяти, динамическое выделение памяти, указатели в чем отличие?
Здравствуйте. Прочитал кучу определений но никак не пойму вообще что к чему. 1)Стек - это якобы кусок оперативной памяти который...

Ошибка с выделением памяти
Помогите с прогой. Какая то ошибка с выделением памяти. В free_result пишет, что вызвано исключение. Подскажите в чем ошибка. Заранее...

Конструктор с выделением памяти
Среди всех данных есть указатель, память для которого выделяется в конструкторе, необходимый размер передается в параметрах конструктора....

60
 Аватар для oxotnik
1665 / 1134 / 80
Регистрация: 21.08.2008
Сообщений: 4,734
Записей в блоге: 1
09.08.2011, 16:08
память выделяется всегда, только в одном случае на стеке, в другом в куче
небольшие объекты лучше на стеке, большие массивы в куче
1
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
09.08.2011, 16:08
если N неизвестно на момент компиляции, то через оператор new выделяем память в куче, если известно - то можно просто в стеке int arr[n];
1
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
09.08.2011, 16:10
Цитата Сообщение от Lindemann66 Посмотреть сообщение
int *arr = new int[n];
- память выделяется динамически в любой свободной части оперативки, причём во время работы приложения при повторномм выделении памяти может быть выделена уже совсем другая область

Цитата Сообщение от Lindemann66 Посмотреть сообщение
int arr[n];
- во время работы адресс начала блока памяти неизменен...
2
12 / 12 / 1
Регистрация: 09.08.2011
Сообщений: 53
09.08.2011, 16:13
Разница также состоит в том, что используя динамическое распределение памяти, вы должны сами явно вписывать уничтожение (освобождение) памяти под этим динамическим объектом, иначе можно получить нечто неконтролируемо пожирающее память..
0
Заблокирован
09.08.2011, 16:16
в стеке память быстрее выделится
0
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
09.08.2011, 16:17
Это
Цитата Сообщение от DoZZer_ Посмотреть сообщение
вы должны сами явно вписывать уничтожение (освобождение) памяти под этим динамическим объектом, иначе можно получить нечто неконтролируемо пожирающее память..
следствие из этого
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
во время работы приложения при повторномм выделении памяти может быть выделена уже совсем другая область
0
Заблокирован
09.08.2011, 16:25
Цитата Сообщение от Lindemann66 Посмотреть сообщение
Всем привет!

Не сочтите за глупость, но возник интересный вопрос, над которым давно думаю, а овтета нигде не находил

Вот нужно, допустим, создать массив из n элементов

Сделать это можно 2-мя способами


C++
1
int arr[n];

и
C++
1
int *arr = new int[n];
Но в одном случае создание массива сопровождается выделением памяти, а в другом - без
В чём принципиальная разница?
Я понимаю, в Qt сразу написано - объекты QObject необходимо создавать с выделением памяти, чтобы не было проблем
Понятно, так и делаем. А тут как правильней?
Любое определение объекта сопровождается выделением памяти! Вопрос только в том, где и как выделяется память.
В первом случае у вас выделяется память в стеке, во втором случае у вас память выделяется в кучи.

Но главное, о чем здесь не упомянули, эти два опреде6ления объявляют два разных типа данных! В первом случае вы действительно определяете массив, а во-втором случае вы определяете указатель. В С++ особенно существенна разница между указателями и массивами, так как sizeof массива отличается от sizeof указателя. И кроме того в С++ могут быть определены функции, аргументами которых являются ссылки на массив. То есть в С++ можно в функции в качестве параметра передавать массивы.

Посмотрите пример шаблонной функции

C++
1
2
3
template <typename T, size_t N>
 
inline size_t array_size( const T ( & )[ N ] ) { return ( N ); }
Я набирал код "на коленках", поэтому в нем могут быть ошибки, но идея понятна: функция позволяет вернуть размерность массива. Для указателей она работать не будет.
2
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
09.08.2011, 16:33
Цитата Сообщение от Сыроежка Посмотреть сообщение
template <typename T, size_t N>
inline size_t array_size( const T ( & )[ N ] ) { return ( N ); }
Зачем так сложно если для статики чётко это работает?
C++
1
sizeof(mass)/sizeof(mass[0]);
Добавлено через 2 минуты
Цитата Сообщение от Сыроежка Посмотреть сообщение
В первом случае вы действительно определяете массив, а во-втором случае вы определяете указатель.
Ну это ты прав, а что мы передаём в функцию, ммм-масив ли?
C++
1
void fun(int m, int * mass);//это я к примеру
0
Заблокирован
09.08.2011, 16:35
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Зачем так сложно если для статики чётко это работает?
C++
1
sizeof(mass)/sizeof(mass[0]);
Вы заблуждаетесь. Как раз в вашем примере все очень сложно. Вам всегда самому нужно писать такое выражение, а в моем случае достаточно записать array_size( array ). Тем более это выражение более самодокументируемо. Не забывайте, что имя массива может быть очень сложным и составным, и тогда ваше выражение можно вообще с ошибками записать.
0
Freelance
Эксперт С++
 Аватар для asics
2891 / 1826 / 356
Регистрация: 09.09.2010
Сообщений: 3,841
09.08.2011, 16:36
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
а что мы передаём в функцию, ммм-масив ли?
Нет, не масив, а адрес первого елемента.
1
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
09.08.2011, 16:37
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Зачем так сложно если для статики чётко это работает?
Зато
C++
1
array_size(array);
компактнее, красивее и легче читается. А главное, это должно защитить от попытки подсунуть туда указатель вместо массива.
0
Заблокирован
09.08.2011, 16:45
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Ну это ты прав, а что мы передаём в функцию, ммм-масив ли?
C++
1
void fun(int m, int * mass);//это я к примеру
Я не понял этого вашего вопроса. Как я указал, нередки случаи в С++, когда передается ссылка на массив. И я привел такой пример для вычисления размерности массива.

Добавлено через 7 минут
Кстати сказать, когда выделяется память в куче для двумерного массива, многие программисты затем испытывают трудности при работе с ним, потому что не знают, как затем обращаться с этим массивом, и как определить указатель на выделенную память.

Например, как правильно задать указатель для выделения памяти выражением вида

new char[m][n];

Здесь уже был такой вопрос на форуме.
1
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
09.08.2011, 16:51
Цитата Сообщение от Сыроежка Посмотреть сообщение
Например, как правильно задать указатель для выделения памяти выражением вида
new char[m][n];
Это делается вот так
C++
1
2
3
char ** pArray = new char *[m];
for(int i = 0; i < m; i++)
pArray[i] = new char[n];
А как быть если в программе нужно изменить длинну какой-либо одной строки
C++
1
pArray[i]
лучше malloc с realloc использовать....
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
09.08.2011, 16:54
Цитата Сообщение от Сыроежка Посмотреть сообщение
Любое определение объекта сопровождается выделением памяти! Вопрос только в том, где и как выделяется память.
В первом случае у вас выделяется память в стеке, во втором случае у вас память выделяется в кучи.

Но главное, о чем здесь не упомянули, эти два опреде6ления объявляют два разных типа данных! В первом случае вы действительно определяете массив, а во-втором случае вы определяете указатель. В С++ особенно существенна разница между указателями и массивами, так как sizeof массива отличается от sizeof указателя. И кроме того в С++ могут быть определены функции, аргументами которых являются ссылки на массив. То есть в С++ можно в функции в качестве параметра передавать массивы.

Посмотрите пример шаблонной функции

C++
1
2
template <typename T, size_t N>
inline size_t array_size( const T ( & )[ N ] ) { return ( N ); }
Я набирал код "на коленках", поэтому в нем могут быть ошибки, но идея понятна: функция позволяет вернуть размерность массива. Для указателей она работать не будет.
Уточню.
1. Массив можно определить не только как локальный, но и как глобальный. Только для локального массива память выделяется в стеке во время работы программы. Для глобального массива память распределяет компилятор и эта память в стандарте называется static storage. Там же размещаются и статические переменные, даже локальные. Нестатические локальные переменные размещаются в автоматической памяти (automation - если не наврал - storage). Стандарт не говорит, что должен быть именно стек. Просто издревле локальные переменные размещались в стеке ВО ВРЕМЯ ВЫПОНЕНИЯ программы. Размещение в стеке массива сразу ограничивает его размер до размера стека, выделяемого по умолчанию операционной системой для программы. Размер можно увеличить, но это надо уже устанавливать режимы линкера.
Размер массива должен быть константным выражением.

2. Во втором случае, как сказал Сыроежка, мы имеем указатель, который проинициализирован адресом первого элемента массива. Причем это делается тоже ВО ВРЕМЯ ВЫПОЛНЕНИЯ программы. Отличие от первого случая - это vds делаем сами, ручками, явными операциями. В первом случае массив автоматом уничтожается, а во втором случае мы должны его убить явно сами операцией delete[]. Размер массива может вычисляться во время работы программы. Подобный массив размещается в динамической памяти (это третий вид памяти для объектов в С++ - dynamic storage). Опять же, как реализовать эту память стандарт не оговаривает.

3. Шаблонная функция, которую написал Сыроежка - это к памяти вообще отношения не имеет. N - это параметр шаблона, который должен быть вычислен на этапе компиляции при инстанцировании шаблона и поставлен в текст функции.
0
Заблокирован
09.08.2011, 16:54
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Это делается вот так
C++
1
2
3
char ** pArray = new char *[m];
for(int i = 0; i < m; i++)
pArray[i] = new char[n];
А как быть если в программе нужно изменить длинну какой-либо одной строки
C++
1
pArray[i]
лучше malloc с realloc использовать....
У меня был конкретный вопрос про выражение

C++
1
new char[n][m];
Вы его подменили другим выражением. Это как раз и подтверждает, что с массивами выделяемыми в куче работать сложнее. Что я и хотел сказать.
0
Freelance
Эксперт С++
 Аватар для asics
2891 / 1826 / 356
Регистрация: 09.09.2010
Сообщений: 3,841
09.08.2011, 16:55
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
лучше malloc с realloc использовать....
Лучше std::vector<std::vector<int>> ипользовать, если пишешь на С++, выдержка стиля все-таки.
1
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
09.08.2011, 16:57
За указатель писал к тому что юзая функции мы всё равно в них указатели передаём, ну а на счёт sizeof - я предпочитаю этот дедовский способ, мне он интуитивно понятней...
На счёт передачи в sizeof динамики - вернётся 4
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
09.08.2011, 16:58
Цитата Сообщение от Сыроежка Посмотреть сообщение
Кстати сказать, когда выделяется память в куче для двумерного массива, многие программисты затем испытывают трудности при работе с ним, потому что не знают, как затем обращаться с этим массивом, и как определить указатель на выделенную память.

Например, как правильно задать указатель для выделения памяти выражением вида

new char[m][n];

Здесь уже был такой вопрос на форуме.
В С++ НЕТ двумерных массивов - только одномерные. Поэтому указанная вами запись - невозможна. Однако элементом массива может быть массив. Поэтому тут все четко: сначала выделяем память под массив (указателей), потом - память под каждый элемент массива - инициализируем указатели.
1
Заблокирован
09.08.2011, 17:00
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
В С++ НЕТ двумерных массивов - только одномерные. Поэтому указанная вами запись - невозможна. Однако элементом массива может быть массив. Поэтому тут все четко: сначала выделяем память под массив (указателей), потом - память под каждый элемент массива - инициализируем указатели.
ВЫ уверены, что указанная запись невозможна? Попробуйте ее использовать, будет ли код компилироваться?

Как-то странно звучит, что в С++ нет двумерных массивов, а в С они есть. Что-то неладно в королевском царстве!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
09.08.2011, 17:00
Помогаю со студенческими работами здесь

Проблема с выделением памяти
Пишу вычислительную задачу thread'ы+OpenGL, при загрузке программы контролирую переменную AllocMemSize. Начиная с некоторого момента...

Проблема с выделением памяти
Всем привет! Нужна помощь. Создаю класс и при компиляции возникает ошибка. Не пойму причину. Помогите пожалуйста. Конструктор должен...

Ошибка с выделением памяти
выдает ошибку в выделении памяти. никто не подскажет почему? если что -задача звучит так примерно вводим веественные числа пока не...

Проблемы с выделением памяти
Здравствуйте. Есть контейнер QList &lt;Node *&gt; В Node свой QList &lt;Node *&gt;. Строю программное дерево разбора выражение. На небольших...

Ошибка в коде с выделением памяти
Не могу понять, в чем проблема? double** FuzzySet::operator&amp;&amp;(FuzzySet* _set) { int k = _set-&gt;set.size(); double** R =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор элементов справочника 1С по перечислениям
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru