Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++ Builder

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 124, средняя оценка - 4.95
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
#1

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

06.02.2013, 10:06. Просмотров 17669. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.02.2013, 10:06
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Создание динамического массива структур и его удаление (C++ Builder):

Создание динамического массива и его инициализация в конструкторе класса - C++ Builder
A1uk, ПравилаИзначальное название темы: "Помогите исправить код". Доброго времени суток. Помоги отредактировать задачу... Необходимо...

Удаление динамического массива - C++ Builder
Создал VCL Forms Application в Builder C++ XE4. При написании алгоритма встал такой вопрос: создаётся динамический массив допустим при...

Удаление динамического массива - C++ Builder
создаю динамический массив туда пишутся данные(кол-во неизвестно), по нажатию кнопки, над динамическим массивом совершаются...

Удаление двумерного динамического массива - C++ Builder
Здравствуйте. Возникла ошибка при удалении двумерного динамического массива: сам код: TStringList** TMP_CAT = new...

Удаление и обнуление динамического массива - C++ Builder
Допустим у меня есть следующие функции void __fastcall TForm1::firstSample(TStringList *allData){ TStringList *tempData = new...

Создание двухмерного динамического массива - C++ Builder
Собственно сабж, как для одномерного это понятно. Создаётся double *X = new double; и удаляется delete X; А как сделать...

36
Avazart
Эксперт С++
7417 / 5507 / 316
Регистрация: 10.12.2010
Сообщений: 24,606
Записей в блоге: 17
07.02.2013, 17:00 #16
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Который всегда будет равен четырем.
Ну правильно это ведь указатель на массив, а не сам массив...

Добавлено через 1 минуту
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Что-то у меня внезапное прозрение - а может delete вовсе и не удаляет ничего, а только вытирает указатель?
Когда кажется креститься нада
Тобиш книги читать... но это видимо не в вашем случае
0
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
07.02.2013, 17:01  [ТС] #17
Цитата Сообщение от Avazart Посмотреть сообщение
Ну правильно это ведь указатель на массив, а не сам массив...
Общий смысл: delete так же ничего не удаляет, а просто заставляет считать, что память под указателем свободна? Но ничего, повторюсь, ничего кроме этого не удаляет.
0
Avazart
Эксперт С++
7417 / 5507 / 316
Регистрация: 10.12.2010
Сообщений: 24,606
Записей в блоге: 17
07.02.2013, 17:03 #18
Цитата Сообщение от SatanaXIII Посмотреть сообщение
а просто заставляет считать, что память под указателем свободна?
А что это как не удаление ?

Только тут указатель не причем, он ничего не знает о памяти кроме размера и просто туда указывает.
0
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
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
mimicria
return (true);
1958 / 1095 / 91
Регистрация: 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
2
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
08.02.2013, 11:01  [ТС] #21
mimicria, спасибо, что еще раз мне напомнили о занулении указателей.
Цитата Сообщение от mimicria Посмотреть сообщение
Нет, не равнозначны. Когда уже престанете страдать ерундой и начнёте читать по теме?
Хорошо. По теме.
SatanaXIII >> delete так же ничего не удаляет, а просто заставляет считать, что память под указателем свободна?
Avazart >> А что это как не удаление ?
SatanaXIII >> А вот это я получается удаляю массив? То есть две следующие записи равнозначны?
Ваша фраза о том, что
Цитата Сообщение от mimicria Посмотреть сообщение
операция delete в C++ безопасна для нулевого указателя.
говорит лишь о том, что те две записи не равнозначны и сначала нужно занулить указатель, а потом уже удалять его сколько душе угодно. Это все бесспорно так и есть. Но вот, как мне показалось, Avazart считает, что равнозначны.
Перфразирую:
SatanaXIII >> delete больше ничего не делает как только освобождает память под указателем на массив?
Avazart >> Это и есть удаление массива.
SatanaXIII >> Удаление указателя на массив это и есть удаление массива?
mimicria >> Нет.
Возвращаясь к теме, если delete что-то делает помимо освобождения указателя, то что?

Как именно он освобождает память? И в чем отличие от простого зануления указателя?
0
mimicria
return (true);
1958 / 1095 / 91
Регистрация: 19.04.2011
Сообщений: 2,345
08.02.2013, 11:20 #22
Цитата Сообщение от SatanaXIII Посмотреть сообщение
и сначала нужно занулить указатель, а потом уже удалять его сколько душе угодно
Ваши фразы говорят о том, что вы совсем не понимаете сути выделения и освобождения памяти. new выделила память и вернула действующий указатель. Эта область памяти в куче помечается как занятая. delete по указателю пометил выделенную память как освобождённую. Обнуление указателя делается на случай повторного вызова delete ПОСЛЕ освобождения памяти. Если вы уверены, что указатель точно больше нигде случайно не будет использован, то обнуление указателя можно и не делать.

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

Добавлено через 4 минуты
Цитата Сообщение от SatanaXIII Посмотреть сообщение
если delete что-то делает помимо освобождения указателя, то что?
Почитайте уже
В языке программирования C++ оператор delete возвращает память, выделенную оператором new, обратно в кучу. Вызов delete должен происходить для каждого вызова new, чтобы избежать утечки памяти. После вызова delete объект, указывающий на этот участок памяти, становится некорректным и не должен больше использоваться. Многие программисты присваивают 0 (нуль-указатель) указателям после использования delete, чтобы минимизировать количество ошибок программирования.
0
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
08.02.2013, 11:32  [ТС] #23
Цитата Сообщение от mimicria Посмотреть сообщение
Ваши фразы говорят о том, что вы совсем не понимаете сути выделения и освобождения памяти.
По этому я и спрашиваю. ) Да, да, да, пойду книжки читать.

Цитата Сообщение от mimicria Посмотреть сообщение
new выделила память и вернула действующий указатель. Эта область памяти в куче помечается как занятая. delete по указателю пометил выделенную память как освобождённую. Обнуление указателя делается на случай повторного вызова delete ПОСЛЕ освобождения памяти.
Вот теперь понятно. Спасибо. Еще бы для полного понимания знать механизм вот этого, в трех словах:
Цитата Сообщение от mimicria Посмотреть сообщение
delete по указателю пометил выделенную память как освобождённую
Но вертаясь к первоначальному вопросу: получается никак нельзя по указателю узнать размер массива? И сам delete так же не знает этого, правильно?
0
mimicria
return (true);
1958 / 1095 / 91
Регистрация: 19.04.2011
Сообщений: 2,345
08.02.2013, 11:45 #24
Цитата Сообщение от SatanaXIII Посмотреть сообщение
получается никак нельзя по указателю узнать размер массива?
Для частных случаев решение возможно, общего решения нет. Да оно и не нужно никому.
Цитата Сообщение от SatanaXIII Посмотреть сообщение
И сам delete так же не знает этого, правильно?
delete вообще ничего не знает, это же функция
Записать, а потом найти количество элементов для вызова деструкторов - задача компилятора.
0
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
08.02.2013, 11:59  [ТС] #25
Цитата Сообщение от mimicria Посмотреть сообщение
Для частных случаев решение возможно, общего решения нет. Да оно и не нужно никому.
Удобнее было бы на мой взгляд. К примеру глобально объявленный массив инициируется в какой-то функции. Зачем мне объявлять глобально инициализирующую переменную и везде ее таскать за собой, когда можно было бы померить массив, когда это потребовалось.

А вон тот мой фокус с вычислением количества элементов целочисленного массива почему сработал?
0
mimicria
return (true);
1958 / 1095 / 91
Регистрация: 19.04.2011
Сообщений: 2,345
08.02.2013, 12:16 #26
Цитата Сообщение от SatanaXIII Посмотреть сообщение
К примеру глобально объявленный массив инициируется в какой-то функции. Зачем мне объявлять глобально инициализирующую переменную и везде ее таскать за собой
Потому что в большинстве хороших программ глобально объявленные массивы, переменные и прочее на самом деле используются крайне редко. Когда вы это поймёте, большинство вопросов отпадут сами собой.
Цитата Сообщение от SatanaXIII Посмотреть сообщение
А вон тот мой фокус с вычислением количества элементов целочисленного массива почему сработал?
Возможно, это тот самый частный случай для отдельно взятого компилятора. Возможно, это совпадение. Вы ведь не все возможные варианты проверили? Например, для массивов структур? Так что пока это не более, чем фокус.
0
SatanaXIII
Супер-модератор
Эксперт С++
5667 / 2712 / 255
Регистрация: 01.11.2011
Сообщений: 6,641
Завершенные тесты: 1
08.02.2013, 12:21  [ТС] #27
Цитата Сообщение от mimicria Посмотреть сообщение
Потому что в большинстве хороших программ глобально объявленные массивы, переменные и прочее на самом деле используются крайне редко. Когда вы это поймёте, большинство вопросов отпадут сами собой.
Понял.

Цитата Сообщение от mimicria Посмотреть сообщение
Возможно, это тот самый частный случай для отдельно взятого компилятора. Возможно, это совпадение. Вы ведь не все возможные варианты проверили? Например, для массивов структур? Так что пока это не более, чем фокус.
Если вас не затруднит, попробуйте провернуть тоже самое у себя. Получится?
0
Avazart
Эксперт С++
7417 / 5507 / 316
Регистрация: 10.12.2010
Сообщений: 24,606
Записей в блоге: 17
08.02.2013, 12:41 #28
C++
1
2
delete mas;
mas = NULL;
Во первых массив удаляют delete[] а не просто delete.
Во вторых после удаления mas продолжает указывать туда где раньше были данные, которых теперь нет
( то есть они могут и дальше там лежать а могут и нет т.е. - мусор )

Добавлено через 3 минуты
Цитата Сообщение от SatanaXIII Посмотреть сообщение
А вон тот мой фокус с вычислением количества элементов целочисленного массива почему сработал?
Работал по тому что то массив, а не указатель на массив
0
gumi250
430 / 397 / 35
Регистрация: 06.02.2012
Сообщений: 1,373
08.02.2013, 13:07 #29
SatanaXIII, соглашусь с вами, что было бы не плохо получать размер массива по указателю на него. Но нет такой ф-ции! Нет и все тут. Вы можете придумать разные фокусы, что бы обойти это, но это только фокусы, сегодня они работают, а завтра нет. Смиритесь с тем, что вам придется таскать с собой размер массива или использовать другие возможности языка (списки, вектора и т.д.).
0
Avazart
Эксперт С++
7417 / 5507 / 316
Регистрация: 10.12.2010
Сообщений: 24,606
Записей в блоге: 17
08.02.2013, 13:09 #30
Цитата Сообщение от gumi250 Посмотреть сообщение
SatanaXIII, соглашусь с вами, что было бы не плохо получать размер массива по указателю на него.
ЗачеМо оно надоВо ?
Если для этого есть контейнеры, а массивы это больше наследие Си
0
08.02.2013, 13:09
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.02.2013, 13:09
Привет! Вот еще темы с ответами:

Создание динамического массива TBitBtn - C++ Builder
Хочу создать динамический массив TBitBtn, но не могу понять как. Знаю что могу создать просто TBitBtn *Area, но мне нужно количество...

Создание динамического массива из компонентов TImage - C++ Builder
Здравствуйте. Объясните мне как можно понятнее как создать такой массив. Смотрела в других темах, но вроде не то. (Этот массив мне нужен...

Создание массива структур - C++ Builder
Добрый день. Умею создавать только фиксированное количество структур, так: struct UserInfo { UnicodeString Name; ...

Создание глобального динамического одномерного массива картинок - C++ Builder
Здравствуйте, помогите создать глобальный динамический одномерный массив картинок. С двумерным я разобралась, а с одномерным проблема. ...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru