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

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

06.02.2013, 10:06. Показов 25256. Ответов 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
8484 / 6151 / 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
8484 / 6151 / 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
8484 / 6151 / 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
8484 / 6151 / 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
8484 / 6151 / 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
8484 / 6151 / 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
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru