Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 124, средняя оценка - 4.95
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
#1

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

06.02.2013, 10:06. Просмотров 18291. Ответов 36

Господа, поясните пожалуйста следующий момент:
http://www.cyberforum.ru/cpp-builder/thread360863.html
создаю структуру:
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):

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

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

Удаление и обнуление динамического массива
Допустим у меня есть следующие функции void __fastcall...

Удаление двумерного динамического массива
Здравствуйте. Возникла ошибка при удалении двумерного динамического массива: ...

Некорректное удаление динамического массива внутри объекта
Здравствуйте, встретился вот такой проблемой: скрин Краткое введение в курс...

36
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 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);
1960 / 1097 / 219
Регистрация: 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
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
08.02.2013, 11:32  [ТС] #23
Цитата Сообщение от mimicria Посмотреть сообщение
Ваши фразы говорят о том, что вы совсем не понимаете сути выделения и освобождения памяти.
По этому я и спрашиваю. ) Да, да, да, пойду книжки читать.

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

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

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

Добавлено через 3 минуты
Цитата Сообщение от SatanaXIII Посмотреть сообщение
А вон тот мой фокус с вычислением количества элементов целочисленного массива почему сработал?
Работал по тому что то массив, а не указатель на массив
0
gumi250
431 / 398 / 57
Регистрация: 06.02.2012
Сообщений: 1,373
08.02.2013, 13:07 #29
SatanaXIII, соглашусь с вами, что было бы не плохо получать размер массива по указателю на него. Но нет такой ф-ции! Нет и все тут. Вы можете придумать разные фокусы, что бы обойти это, но это только фокусы, сегодня они работают, а завтра нет. Смиритесь с тем, что вам придется таскать с собой размер массива или использовать другие возможности языка (списки, вектора и т.д.).
0
Avazart
Эксперт С++
7674 / 5583 / 541
Регистрация: 10.12.2010
Сообщений: 25,046
Записей в блоге: 17
08.02.2013, 13:09 #30
Цитата Сообщение от gumi250 Посмотреть сообщение
SatanaXIII, соглашусь с вами, что было бы не плохо получать размер массива по указателю на него.
ЗачеМо оно надоВо ?
Если для этого есть контейнеры, а массивы это больше наследие Си
0
gumi250
431 / 398 / 57
Регистрация: 06.02.2012
Сообщений: 1,373
08.02.2013, 13:17 #31
массивы быстрее
0
Avazart
Эксперт С++
7674 / 5583 / 541
Регистрация: 10.12.2010
Сообщений: 25,046
Записей в блоге: 17
08.02.2013, 13:19 #32
Цитата Сообщение от gumi250 Посмотреть сообщение
массивы быстрее
На много ли?
И вообще не факт после оптимизации..
0
gumi250
431 / 398 / 57
Регистрация: 06.02.2012
Сообщений: 1,373
08.02.2013, 13:44 #33
Вот в этом примере у меня получилось 20.5 сек против 15 в пользу массивов
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    valarray<double> V1(10000000);
    valarray<double> V2(10000000);
    valarray<double> V3(10000000);
    int N=GetTickCount();
    for(int n=0; n<100; n++)
    {   for(int i = 1; i <= 10000000; i++)
        {
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
        }
    }
    ShowMessage(GetTickCount()-N);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    double* V1=new double[10000000];
    double* V2=new double[10000000];
    double* V3=new double[10000000];
    int N=GetTickCount();
    for(int n=0; n<100; n++)
    {   for(int i = 1; i <= 10000000; i++)
        {
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
            V1[i] = 1;
            V2[i] = V1[i];
            V3[i] = V2[i];
        }
    }
    ShowMessage(GetTickCount()-N);
    delete[] V1;
    delete[] V2;
    delete[] V3;
}
1
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
08.02.2013, 13:47  [ТС] #34
Цитата Сообщение от Avazart Посмотреть сообщение
Работал по тому что то массив, а не указатель на массив
Имя массива это и есть указатель на его первый элемент. Или нет?

Цитата Сообщение от Avazart Посмотреть сообщение
Во первых массив удаляют delete[] а не просто delete.
Запомнили.
Цитата Сообщение от Avazart Посмотреть сообщение
Во вторых после удаления mas продолжает указывать туда где раньше были данные, которых теперь нет
( то есть они могут и дальше там лежать а могут и нет т.е. - мусор )
Да. Все так. mas = NULL это просто защита от собственных ошибок.
0
gumi250
431 / 398 / 57
Регистрация: 06.02.2012
Сообщений: 1,373
08.02.2013, 13:56 #35
Если в моем примере который я написал выше, поменять double на int, то выигрыш становится еще существеннее 12сек против 7.5 в пользу массивов
0
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
04.04.2013, 15:12  [ТС] #36
А ведь есть еще оператор new[]. Но по умолчанию компилятор сам распознает и вставляет его на место обяного new.
1
Nekto
342 / 287 / 37
Регистрация: 23.03.2012
Сообщений: 838
09.09.2013, 11:19 #37
Цитата Сообщение от gumi250 Посмотреть сообщение
массивы быстрее
Можно вообще на ассемблер перейти. Что случится с памятью, выделенной под V1, если при выделении V2\V3 выскочит какой-то ексепшн? В случае с контейнерами она освободится, а в случае с массивами?
0
09.09.2013, 11:19
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.09.2013, 11:19
Привет! Вот еще темы с решениями:

Создание динамического массива TBitBtn
Хочу создать динамический массив TBitBtn, но не могу понять как. Знаю что...

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

Создание динамического массива из компонентов TImage
Здравствуйте. Объясните мне как можно понятнее как создать такой массив....

Создание массива структур
Добрый день. Умею создавать только фиксированное количество структур, так: ...


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

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

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