Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.82/119: Рейтинг темы: голосов - 119, средняя оценка - 4.82
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906

Создание динамического массива структур и его удаление

06.02.2013, 10:06. Показов 25403. Ответов 36

Студворк — интернет-сервис помощи студентам
Господа, поясните пожалуйста следующий момент:
создаю структуру:
C++
1
2
3
4
5
6
7
struct TTagList
  {    
  WideString Comment;            
  int State;             
  bool Visible;         
  };
TTagList *TTList;
далее в функции:
C++
1
2
int SomeCount = 15;
TTList = new TTagList[SomeCount];
обращаюсь к элементам "динамической структуры" (вдруг кому пригодится):
C++
1
2
3
4
5
TTList[0].Visible = true;
TTList[0].State = 1;
TTList[0].Comment = L"Комментарий";
TTList[1].Visible = false;
...
удаляю следующим образом:
C++
1
delete [] TTList;
Вопрос: как delete узнает сколько чего удалять, когда как sizeof дальше четырехбайтного указателя ничего не видит?
P.S. И правильно ли удалять такую конструкцию именно delete [], а не просто delete?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.02.2013, 10:06
Ответы с готовыми решениями:

Удаление динамического массива структур
Если удалять массив структур как обычно пишут, то при запросе следующей структуры из массива на вывод она отображается. То есть происходит...

Создание копии динамического массива структур
Есть динамический массив структур, есть сортировка. Проблема заключается в том, что если сделать сортировку, то массив изменится, а мне это...

Создание динамического массива структур
Нужно создать структуру с тремя переменными char int int С динамическим увеличением памяти для задавания их через ...

36
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
06.02.2013, 12:05
Правило простое, если new[], то и delete []

По 1 вопросу: после new возвращается указатель на блок выделенной памяти, перед этим блоке формируются дополнительные байты, в которых хранится размер, delete оттуда и берет информацию о том, сколько надо освободить памяти.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
06.02.2013, 13:25  [ТС]
Грубо говоря, на два объявленных TTList-a new разместит в ячейках памяти приблизительно следующее:

Да? Но если delete знает сколько ему удалять, то почему нельзя таким образом выяснить и размер занимаемой памяти?

Правило простое, если new[], то и delete []
Обратное, если без скобок, верно?
0
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
06.02.2013, 14:31
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Но если delete знает сколько ему удалять, то почему нельзя таким образом выяснить и размер занимаемой памяти?
Позвольте процитировать т-ща Тарасевича с RSDN:

E>Логика: мы не можем ..., а компилятор — может, меня и смутила.
E>Вопрос произошел от указанной темы об определении размера массива, поэтому и стало интересно, кто чего может. То есть я перефразировал бы свою мысль следующим образом: почему компилятор имеет средства для определения размера массива (то есть количества элементов), а программа таких стандартных средств не имеет.

Я совсем недавно отвечал на точно такой же вопрос в comp.lang.c++:

http://groups.google.com/group... otmail.com

Еще раз и по-русски:

Компилятор совсем не обязательно имеет средства для определения размера массива, выделенного в динамической памяти. Он компилятора требуется только то, чтобы он умел правильно выделять такие массивы при помощи 'new[]' и правильно уничтожать такие массивы при помощи 'delete[]'. Как компилятор это делает и какая дополнительная информация понадобится для этого компилятору и понадобится ли она вообще — личное дело компилятора. Классическим примером такой дополнительной информации является количество сконструированных элементов в массиве, которое нужно, например, для того, чтобы правильно выполнить деструкцию элементов массива. Если компилятору эта информация нужна только для того и только для того, чтобы вызвать правильное количество деструкторов, то сразу приходит на ум очевидная оптимизация: если хранимые в массиве объекты не имеют деструкторов (т.е. не являются экземплярами классов) или имеют тривиальные деструкторы (т.е. фактически тоже не имеют деструкторов), то знать количество элементов в массиве компилятору совершенно незачем, и формировать и хранить это количество нигде не надо. Эту оптимизацию используют многие компиляторы, включая MSVC и GCC.

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

Во-вторых, для единообразия, пришлось бы поддержать эту функциональность и для статических и автоматических массивов, что тоже несколько противречит общему духу встроенных С/С++ массивов.

Все это, на мой взгляд, выглядит совершенно не нужно. Особенно если учесть, что пользователь при выделении массива держал в руках его размер и мог сам позаботиться о сохранении этого размера для дальнейшего использования.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
06.02.2013, 15:23  [ТС]
То есть (прочитал вдумчиво и шесть раз) механизм запоминания/определения размера динамически выделенного массива существует, но просто он не унифицирован для разных компиляторов и следовательно специально сделан недоступным?


И куча мелких вопросов в попытке как-то оправдать свое непонимание:
Цитата Сообщение от mimicria Посмотреть сообщение
Во-вторых, для единообразия, пришлось бы поддержать эту функциональность и для статических...массивов
Дык вроде тот же sizeof размер статических массивов прекрасно достает.
Цитата Сообщение от mimicria Посмотреть сообщение
почему компилятор имеет средства для определения размера массива (то есть количества элементов), а программа таких стандартных средств не имеет.
Почему, зная какой ты в данный момент используешь компилятор, все равно нельзя докопаться до размера? Какое-нибудь описание найти для каждого вида и версии компиляторов. Это совсем, я постесняюсь спросить, дебилизм? Х)
0
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
06.02.2013, 17:16
Какой практический интерес докопаться до размера через указатель? Он не зря написал
Цитата Сообщение от mimicria Посмотреть сообщение
Особенно если учесть, что пользователь при выделении массива держал в руках его размер и мог сам позаботиться о сохранении этого размера для дальнейшего использования.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
07.02.2013, 12:13  [ТС]
Цитата Сообщение от mimicria Посмотреть сообщение
Какой практический интерес докопаться до размера через указатель?
Так delete же берет именно размер именно по указателю. Интерес? - чтобы не таскать за собой еще и переменную с размером, к примеру.
Ведь не нужно же писать типа
C++
1
delete [intMasSize] Mas
так почему ж нельзя
C++
1
for(int i=0; i<sizeof(Mas); i++)
Но это, как я понимаю, уже вопрос к создателям компиляторов.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.02.2013, 15:14
delete[] вызывает деструктор каждого объекта класса TTagList в динамическом массиве.
Вся остальная ответственность за удаление полей структуры на деструкторе.
0
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
07.02.2013, 15:34
Цитата Сообщение от Avazart Посмотреть сообщение
delete[] вызывает деструктор каждого объекта класса TTagList в динамическом массиве.
Да вот ему интересно, откуда delete знает, сколько вызывать деструкторов?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.02.2013, 15:41
Ну обычно компилятор записывает инфу о количестве в ячейках предшествующих массиву.

Добавлено через 1 минуту
Типа N, a[0], a[1], ... a[N]
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
07.02.2013, 16:07  [ТС]
Цитата Сообщение от mimicria Посмотреть сообщение
Да вот ему интересно, откуда delete знает, сколько вызывать деструкторов?
В точку!

Цитата Сообщение от Avazart Посмотреть сообщение
Ну обычно компилятор записывает инфу о количестве в ячейках предшествующих массиву.
Типа N, a[0], a[1], ... a[N]
Ага. mimicria, уже писал об этом. Но толку? )

Добавлено через 1 минуту
Цитата Сообщение от Avazart Посмотреть сообщение
Типа N, a[0], a[1], ... a[N]
почему же sizeof не может обратиться к этому N, когда оно вот прям лежит - бери не хочу?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.02.2013, 16:36
Цитата Сообщение от SatanaXIII Посмотреть сообщение
почему же sizeof не может обратиться к этому N, когда оно вот прям лежит - бери не хочу?
Вы о чем ?

C++
1
sizeof(A[5]);
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
07.02.2013, 16:46  [ТС]
О том, что
C++
1
2
sizeof(A); // не сработает.
delete A; // сработает
Десять отличий?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.02.2013, 16:47
Сработает почему нет ?

C++
1
2
3
4
5
6
7
8
9
10
11
int A[10];
 
sizeof(A)  //  = sizeof(int) *10
 
int* B= new B[10];
 
sizeof(B)  //  = sizeof(int*) ;
 
int* p= B+5; // B[5]
 
sizeof(*p) // = sizeof(int);
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
07.02.2013, 16:57  [ТС]
Нас интересует случай с
C++
1
sizeof(B);
Который всегда будет равен четырем.

Что-то у меня внезапное прозрение - а может delete вовсе и не удаляет ничего, а только вытирает указатель?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.02.2013, 17:00
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Который всегда будет равен четырем.
Ну правильно это ведь указатель на массив, а не сам массив...

Добавлено через 1 минуту
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Что-то у меня внезапное прозрение - а может delete вовсе и не удаляет ничего, а только вытирает указатель?
Когда кажется креститься нада
Тобиш книги читать... но это видимо не в вашем случае
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
07.02.2013, 17:01  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Ну правильно это ведь указатель на массив, а не сам массив...
Общий смысл: delete так же ничего не удаляет, а просто заставляет считать, что память под указателем свободна? Но ничего, повторюсь, ничего кроме этого не удаляет.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.02.2013, 17:03
Цитата Сообщение от SatanaXIII Посмотреть сообщение
а просто заставляет считать, что память под указателем свободна?
А что это как не удаление ?

Только тут указатель не причем, он ничего не знает о памяти кроме размера и просто туда указывает.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
08.02.2013, 09:48  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
А что это как не удаление ?
А вот это я получается удаляю массив?
C++
1
2
int * mas = new int[10];
mas = NULL; // nullptr
То есть две следующие записи равнозначны?
C++
1
2
delete mas;
mas = NULL;
Цитата Сообщение от Avazart Посмотреть сообщение
Только тут указатель не причем, он ничего не знает о памяти кроме размера и просто туда указывает.
А кто тогда знает? Почему при объявлении массива из десяти(10) четырехбайтных(4) int-ов выделится сорок(10*4) байт к ряду и никто кроме самого массива в эти сорок байт ничего не запишет. Где-то же хранится информация о размере массива. Она где-то есть, это факт.
Вот методом научного тыка, по предположению, что она лежит перед первым элементом массива проведен следующий эксперимент (работает птолько с целочисленным массивом):
C++
1
2
3
4
5
6
7
int * mas;
int count = 7;
mas = new int[count];
for(int i=0; i<count; i++)
  mas[i]=i+1;
 
ShowMessage(mas[-1]);
При разных значениях count получаем разные значения mas[-1]. Среди них прослеживается четкая закономерность. Вот она:
Code
1
2
3
4
5
6
7
8
9
10
11
12
0   =  14 (6 должно быть)
1   =  14 (10 должно быть)
2   =  14
3   =  18
4   =  22
5   =  26
6   =  30
7   =  34
   ...
10  =  46
   ...
100 =  406
При значениях count меньше двух (три элемента массива и менее) видно, что по mas[-1] лежит значение 14. Из чего можно сделать предположение, что при объявлении массива память выделяется сразу под три элемента минимум (избыточность?). Так же к находящемуся в mas[-1] значению приплюсовывается еще значение 6, 4 из которых, вероятно, это размер самого mas[-1] и 2 - хз. Таким образом, при размере целочисленного массива больше трех, можно вычислить точный его размер по формуле: (mas[-1]-6)/sizeof(int).

P.S. Builder 6 Build 10.161
P.P.S. Я думаю можно найти расположения и для остальных типов данных, мониторя всю память. Но легче узнать устройство компилятора и так выяснить куда он что пишет.
0
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
08.02.2013, 10:00
Цитата Сообщение от SatanaXIII Посмотреть сообщение
То есть две следующие записи равнозначны?
Нет, не равнозначны. Когда уже престанете страдать ерундой и начнёте читать по теме?

Нулевые указатели придуманы как удобный способ «отметить» указатели, которые заведомо не указывают на корректный адрес в памяти. Например, при объявлении указателя как автоматической переменной его значение не определено. Чтобы отметить, что этот указатель ещё не содержит корректный адрес в памяти, такому указателю присваивают константу нулевого указателя:
C++
1
2
3
4
5
void f(void)
{
  int *x = NULL;
  /* ... */
}
Хорошим стилем программирования является присваивание указателю после освобождения памяти, на которую он ссылался, нулевого указателя.Кроме этого, применение обнуления указателей актуально для безопасности освобождения памяти: операция delete в C++ (free в Си) безопасна для нулевого указателя. Например:
C++
1
2
3
4
5
TYPE *foo = new TYPE();
//использование foo
delete foo;// foo != NULL
//еще 100 строк кода
delete foo;//ОШИБКА! память уже недоступна
в то время как в таком варианте ошибки не будет
C++
1
2
3
4
5
6
TYPE *foo = new TYPE();
//использование foo
delete foo;// foo != NULL
foo = NULL;// foo == NULL
//еще 100 строк кода
delete foo;//ошибки нет: delete проверяет значение foo
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.02.2013, 10:00
Помогаю со студенческими работами здесь

Преобразование кода в ряд структур, создание динамического массива
Здравствуйте, у меня вопрос, как данный ниже код можно преобразовать в структурах, чтобы массив был динамическим #include...

Удаление динамического массива с сохранением его значений
как в функции add удалить дин массив ptzz но при этом оставить его значения в ptz? #include &lt;iostream&gt; #include &lt;ctime&gt; ...

Создание динамического массива и его заполнение
как можно создать динамический массив чтобы пользователь сам ввел размерность и заполнил его? вот мои наработки. массив вроде создал, но...

Создание динамического массива и его обработка
Сформировать одномерный массив. Удалить из него элемент с заданным номером, добавить К элементов, начиная с заданного номера;

Ошибка, создание динамического массива и его вывод
есть часть кода всей программы , выполняется неверно или вообще не выполняется... в чем ошибка подскажите .. УСЛОВИЕ Должен быть...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru