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

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

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

Author24 — интернет-сервис помощи студентам
Господа, поясните пожалуйста следующий момент:
создаю структуру:
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);
1976 / 1111 / 221
Регистрация: 19.04.2011
Сообщений: 2,345
06.02.2013, 12:05 2
Правило простое, если new[], то и delete []

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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
Почетный модератор
Эксперт С++
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
07.02.2013, 16:57  [ТС] 15
Нас интересует случай с
C++
1
sizeof(B);
Который всегда будет равен четырем.

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

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

Только тут указатель не причем, он ничего не знает о памяти кроме размера и просто туда указывает.
0
Почетный модератор
Эксперт С++
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
08.02.2013, 09:48  [ТС] 19
Цитата Сообщение от 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]. Среди них прослеживается четкая закономерность. Вот она:
Код
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);
1976 / 1111 / 221
Регистрация: 19.04.2011
Сообщений: 2,345
08.02.2013, 10:00 20
Цитата Сообщение от 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
08.02.2013, 10:00
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.02.2013, 10:00
Помогаю со студенческими работами здесь

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

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

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

Ошибка, создание динамического массива и его вывод
есть часть кода всей программы , выполняется неверно или вообще не выполняется... в чем ошибка...

Создание динамического массива строк и его сортировка
Как создать динамический массив строк в Си и отсортировать его?

Создание динамического массива и его инициализация в конструкторе класса
A1uk, ПравилаИзначальное название темы: &quot;Помогите исправить код&quot;. Доброго времени суток. Помоги...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Как написать микросервис на Go/Golang
InfoMaster 14.01.2025
Определение микросервиса, преимущества использования Go/ Golang Микросервис – это архитектурный подход к разработке программного обеспечения, при котором приложение состоит из небольших, независимо. . .
Как написать микросервис с нуля на C#
InfoMaster 14.01.2025
В современном мире разработки программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот архитектурный подход предполагает. . .
Как создать интернет-магазин на PHP и JavaScript
InfoMaster 14.01.2025
В современном мире электронная коммерция стала неотъемлемой частью бизнеса. Создание собственного интернет-магазина открывает широкие возможности для предпринимателей, позволяя достичь большей. . .
Как написать Тетрис на Ассемблере
InfoMaster 14.01.2025
Тетрис – одна из самых узнаваемых и популярных компьютерных игр, созданная в 1984 году советским программистом Алексеем Пажитновым. За прошедшие десятилетия она завоевала симпатии миллионы людей по. . .
Как создать игру "Танчики" на Unity3d и C#
InfoMaster 14.01.2025
Разработка игр – это увлекательный процесс, сочетающий в себе творчество и технические навыки. В этой статье мы рассмотрим создание классической игры "Танчики" с использованием Unity3D и языка. . .
Организую платный онлайн микро-курс по доработке Android-клиента Telegram
_Ivana 14.01.2025
Официальная версия и распространенные форки не полностью устраивают? Сделай свою кастомную версию клиента! 4 занятия по 2 часа (2 недели пн, ср 19:00-21:00 по Москве). Первое вводное занятие. . .
Как создать приложение для фитнеса для iOS/iPhone на Kotlin
InfoMaster 14.01.2025
Создание собственного фитнес-приложения — это не только захватывающий, но и полезный процесс, ведь оно может стать вашим верным помощником на пути к здоровому и активному образу жизни. В современных. . .
Как создать приложение магазина для iOS/iPhone на Swift
InfoMaster 14.01.2025
Введение в разработку iOS-приложений Разработка приложений для iPhone и других устройств на базе iOS открывает огромные возможности для создания инновационных мобильных решений. В данной статье мы. . .
Это работает. Скорость асинхронной логики велика. Вопрос видимо останется в стабильности. Плата - огонь!
Hrethgir 13.01.2025
По прошлому проекту в Logisim Evolution https:/ / www. cyberforum. ru/ blogs/ 223907/ blog8781. html прилагаю файл архива проекта в Gowin Eda. Восьмибитный счётчик из сумматора+ генератор сигнала. . .
UserScript для подсветки кнопок языков программировани­­­­я в зависимости от текущего раздела
volvo 13.01.2025
В результате работы этого скрипта подсвечиваются нужные кнопки не только в форме быстрого ответа, но и при редактировании сообщения: / / ==UserScript== / / @name CF_DefaultLangSelect / / . . .
Введение в модели и алгоритмы машинного обучения
InfoMaster 12.01.2025
Машинное обучение представляет собой одну из наиболее динамично развивающихся областей искусственного интеллекта, которая фокусируется на разработке алгоритмов и методов, позволяющих компьютерам. . .
Как на Python создать нейросеть для решения задач
InfoMaster 12.01.2025
В контексте стремительного развития современных технологий особое внимание уделяется таким инструментам, как нейросети. Эти структуры, вдохновленные биологическими нейронными сетями, используются для. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru