Многоуважаемые дельфи-гуру, помогите!
Страдаю второй год! Никак не пойму (все мои друзья-гуру не могут мне объяснить).
Слыхал от людей, что все объекты в обжект паскале динамические.
1. Когда объект (т.е. указатель) выходит за пределы видимости, то уничтожается ли объект? Или я обязан явно вызвать деструктор?
2. Cтало быть, все объекты в куче?
3. Если есть два динамических массива А и В, то A:=B; приводит к освобождению памяти, на которую до этого ссылался А?
Помогите!
Здравствуйте, delphi_teapot, Вы писали:
DT>Многоуважаемые дельфи-гуру, помогите! DT>Страдаю второй год! Никак не пойму (все мои друзья-гуру не могут мне объяснить). DT>Слыхал от людей, что все объекты в обжект паскале динамические. DT>1. Когда объект (т.е. указатель) выходит за пределы видимости, то уничтожается ли объект? Или я обязан явно вызвать деструктор? DT>2. Cтало быть, все объекты в куче? DT>3. Если есть два динамических массива А и В, то A:=B; приводит к освобождению памяти, на которую до этого ссылался А? DT>Помогите!
Здесь нет ничего сложного. Если ты создал объект (вызвав его конструктор), то ты обязан его уничтожить. Простое объявление переменной объекта приводит просто к выделению памяти под указатель, область памяти, где будет храниться адрес настоящего объекта. При выходе из области видимости объекты не уничтожаются, уничтожаются толко динамические массивы, строки и объекты, представленные как интерфейсы.
То есть если ты вызвал конструктор, но потом забыл вызвать деструктор, объект будет существовать в течении всего времени жизни программы.
Присвоение A := B просто приводит к копированию значения адреса объекта, то две переменные теперь указывают на один объект, естественно, что ничего не освобождаются. Если потом вызвать A.Free, то вызывать B.Free будет нельзя, ибо объект уже уничтожен... Ну и так далее...
Здравствуйте, delphi_teapot, Вы писали:
DT>Из твоего знатного ответа я только одного не понял, как быть с A:=B; т.е. я предварительно должен освободить память А?
А, ты имеешь ввиду, что A уже указывает на какой-то объект? В таком случае, если ты так сделаешь, то просто потеряешь в памяти этот объект и, соответсвенно, не сможешь его удалить более. Так что да, объект A нужно освободить вручную, если он уже не нужен, ну или в каку-нить временную переменную скопировать (адрес, а не объект), если еще нужен.
Здравствуйте, Demiurg, Вы писали:
D>Здравствуйте, delphi_teapot, Вы писали:
DT>>Из твоего знатного ответа я только одного не понял, как быть с A:=B; т.е. я предварительно должен освободить память А?
D> А, ты имеешь ввиду, что A уже указывает на какой-то объект? В таком случае, если ты так сделаешь, то просто потеряешь в памяти этот объект и, соответсвенно, не сможешь его удалить более. Так что да, объект A нужно освободить вручную, если он уже не нужен, ну или в каку-нить временную переменную скопировать (адрес, а не объект), если еще нужен.
Ну... это если в классе не реализован подсчет ссылок...
Если же реализован (см. про интерфейсы), то при присваивании А:=... уменьщается число ссылок на объект, на который указывал A и, если оно (число ссылок) =0, то Free вызывается автоматически...
Здравствуйте, delphi_kettle, Вы писали:
DK>Здравствуйте, Demiurg,
DK>Прочитал я это сообщение и подумал как же нам, дельфистам, повезло с языком! Так удобно и надежно все придумано!
Здравствуйте, s.ts, Вы писали:
ST>Ну... это если в классе не реализован подсчет ссылок... ST>Если же реализован (см. про интерфейсы), то при присваивании А:=... уменьщается число ссылок на объект, на который указывал A и, если оно (число ссылок) =0, то Free вызывается автоматически...
Конечно, про интерфейсы понятно, где-то выше писал...Любой класс можно унаследовать от чисто абстрактного класса с помощью слова Interface, а не Class, тогда и будет работать подсчет ссылок, освобождение при выходе из области видимости, короче все прелести Однако есть и неудобства по сравнению с обычными классами...
Здравствуйте, s.ts, Вы писали:
DK>>Прочитал я это сообщение и подумал как же нам, дельфистам, повезло с языком! Так удобно и надежно все придумано!
ST>Что именно-то ?
То что при выходе из области действия ничего не уничтожается автоматически. Не то что в этом запутанном си++. Правда мои друзья, использующие си++, меня дураком называют, все твердят про какие-то утечки. Какая разница?! Дельфи == язык чайников!
Здравствуйте, Demiurg, Вы писали:
D>Здравствуйте, s.ts, Вы писали:
ST>>Ну... это если в классе не реализован подсчет ссылок... ST>>Если же реализован (см. про интерфейсы), то при присваивании А:=... уменьщается число ссылок на объект, на который указывал A и, если оно (число ссылок) =0, то Free вызывается автоматически...
D> Конечно, про интерфейсы понятно, где-то выше писал...Любой класс можно унаследовать от чисто абстрактного класса с помощью слова Interface, а не Class, тогда и будет работать подсчет ссылок, освобождение при выходе из области видимости, короче все прелести Однако есть и неудобства по сравнению с обычными классами...
Я бы сказал иначе: любой класс может реализовывать интерфейсы. Наследовать можно от класса и интерфейса — это замена множественному наследованию, используемая в "новых" языках типа delphi, java etc.
А подсчет ссылок можно реализовать просто напросто унаследовав от TInterfacedObject — тут, наверное, не нужно даже и про интерфейсы ничего знать.
Здравствуйте, Demiurg, Вы писали:
D>Здравствуйте, delphi_kettle, Вы писали:
D> DK>>Прочитал я это сообщение и подумал как же нам, дельфистам, повезло с языком! Так удобно и надежно все придумано!
D> Хммм... Мне тоже нравится ссылочная модель, реализованная в Дельфи, но в С++ ООП мне все же нравится больше
Поддерживаю двумя руками
Тем более, что "ссылочная модель", фактически по возмозможностям является подмножеством множественного наследования + переопределение операторов (С++), но реализована на уровне компилятора.
Здравствуйте, delphi_kettle, Вы писали:
DK>Здравствуйте, s.ts, Вы писали:
DK>>>Прочитал я это сообщение и подумал как же нам, дельфистам, повезло с языком! Так удобно и надежно все придумано!
ST>>Что именно-то ?
DK>То что при выходе из области действия ничего не уничтожается автоматически. Не то что в этом запутанном си++. Правда мои друзья, использующие си++, меня дураком называют, все твердят про какие-то утечки. Какая разница?!
Ну, обзываться не стоит... Все дело вкусов. Но delphi отражает общую тенденцию в развитии языков программирования. Из распространенных языков только c++, наверное, и поддерживает множественное наследование. Но если использовать Borland С++, то есть выбор — там и ANSI поддерживается и интерфейсы.
DK> Дельфи == язык чайников!
Дык и на CBuilder можно программы мышкой рисовать в одном OnClik-е 8)
Просто с него (c delphi) многие начинают — отсюда и расхожее мнение. Мне тот-же C++ не кажется более сложным. Сложными могут быть кривые С++ библиотеки, основанные на макросах (кто знает-поймет).
Здравствуйте, delphi_kettle, Вы писали:
ST>>Что именно-то ? DK>То что при выходе из области действия ничего не уничтожается автоматически. Не то что в этом запутанном си++.
Я сначала подумал, что ты так иронизируешь. Но ты, похоже, серьезно Прелесть автоматического уничтожения объектов проще всего можно постичь ковырясь в VCL и наблюдая повсюду уродские try/finally.
DK>Правда мои друзья, использующие си++, меня дураком называют, все твердят про какие-то утечки. Какая разница?! Дельфи == язык чайников!
Пусть твои друзья называют дураками тех, кто придумал саму дельфю, точнее ее язык. Потому как отсутствие автоматического уничтожения объектов, наряду с отстутствием какой-либо системы сборки мусора, для современного прикладного языка высокого уровня — просто несерьезно. И чайникам этот язык противопоказан прежде всего, пока они не поймут что такое "утечки". Хотя если дельфя плавно перейдет в Delphi.NET, то все не так грустно. Но это будет уже другой язык, пусть и с такими же begin/end.
P.S. Готов принять кучу нулей от поклонников дельфей Желательно аргументированные (и, наверное, в другом форуме)
[эмоции skipped]
В>... Потому как отсутствие автоматического уничтожения объектов, наряду с отстутствием какой-либо системы сборки мусора, для современного прикладного языка высокого уровня — просто несерьезно.
А в С++ существует какая-либо встроенная система уборки мусора для объектов создаваемых в куче?
Здравствуйте, s.ts, Вы писали:
ST>Поддерживаю двумя руками ST>Тем более, что "ссылочная модель", фактически по возмозможностям является подмножеством множественного наследования + переопределение операторов (С++), но реализована на уровне компилятора.
Не понял. Что реализовано на уровне компилятора? И какое отношение ссылочная модель имеет к переопределению операторов?
Здравствуйте, mrhru, Вы писали:
В>>... Потому как отсутствие автоматического уничтожения объектов, наряду с отстутствием какой-либо системы сборки мусора, для современного прикладного языка высокого уровня — просто несерьезно. M>А в С++ существует какая-либо встроенная система уборки мусора для объектов создаваемых в куче?
В С++ существует автоматическое уничтожение объектов. Встроенная система уборки мусора есть, например, в джаве. То и другое (с ограничениями) есть в C#. Нету ни того ни другого в С (без плюсов), в этом плане он очень похож на дельфю Но он при этом и на язык высокого уровня особо не претендует, скорее это "переносимый ассемблер".
Здравствуйте, Владик, Вы писали:
В>Здравствуйте, mrhru, Вы писали:
В>>>... Потому как отсутствие автоматического уничтожения объектов, наряду с отстутствием какой-либо системы сборки мусора, для современного прикладного языка высокого уровня — просто несерьезно. M>>А в С++ существует какая-либо встроенная система уборки мусора для объектов создаваемых в куче?
В>В С++ существует автоматическое уничтожение объектов.
Не совсем правильно. Для объектов в стеке, а не в куче.
В>Встроенная система уборки мусора есть, например, в джаве. То и другое (с ограничениями) есть в C#. Нету ни того ни другого в С...
Тоже неправильно. Объекты в стеке самоликвидируются.
В> (без плюсов), в этом плане он очень похож на дельфю
И это неправильно.
В> Но он при этом и на язык высокого уровня особо не претендует, скорее это "переносимый ассемблер".
Опять неправильно. С всегда относится к языкам высокого уровня.
Здравствуйте, mrhru, Вы писали:
В>>В С++ существует автоматическое уничтожение объектов. M>Не совсем правильно. Для объектов в стеке, а не в куче.
Стэк здесь не причем. Агрегируемые объекты также автоматически разрушаются, при этом агрегирующий объект может находится где угодно. В С++ вообще нет понятие стэка (или кто-нибудь ткнет меня носом в соответсвующее место стандарта?), есть понятие области видимости.
В>>Встроенная система уборки мусора есть, например, в джаве. То и другое (с ограничениями) есть в C#. Нету ни того ни другого в С... M>Тоже неправильно. Объекты в стеке самоликвидируются.
Начнем с того, что в С нет объектов. Или уточни, что ты понимаешь под объектами (с философской точки зрения это может быть что угодно).
В>> (без плюсов), в этом плане он очень похож на дельфю M>И это неправильно.
Что неправильно? Необходимость ручного управления ресурсами без возможности хоть как-то автоматизировать их освобождение? Где неправильно?
В>> Но он при этом и на язык высокого уровня особо не претендует, скорее это "переносимый ассемблер". M>Опять неправильно. С всегда относится к языкам высокого уровня.
Официально — да. По сравнению с другими языками высокого уровня — он имеет ну очень низкий уровень.
Здравствуйте, Владик, Вы писали:
В>>>В С++ существует автоматическое уничтожение объектов. M>>Не совсем правильно. Для объектов в стеке, а не в куче.
В>Стэк здесь не причем. Агрегируемые объекты также автоматически разрушаются, при этом агрегирующий объект может находится где угодно. В С++ вообще нет понятие стэка (или кто-нибудь ткнет меня носом в соответсвующее место стандарта?), есть понятие области видимости.
В>>>Встроенная система уборки мусора есть, например, в джаве. То и другое (с ограничениями) есть в C#. Нету ни того ни другого в С... M>>Тоже неправильно. Объекты в стеке самоликвидируются.
В>Начнем с того, что в С нет объектов. Или уточни, что ты понимаешь под объектами (с философской точки зрения это может быть что угодно).
Прототип объектов в С++ — структуры.
В>>> (без плюсов), в этом плане он очень похож на дельфю M>>И это неправильно.
В>Что неправильно? Необходимость ручного управления ресурсами без возможности хоть как-то автоматизировать их освобождение? Где неправильно?
В С нет возможности хоть как-то автоматизировать освобождение объектов, в Delphi — есть.
1) Это, уже упоминавшиеся, интерфейсы. Для них компилятор гарантирут вызовы виртуальных AddRef и Release объектов, которые "скрываются" за интерфейсами. И дело программистов — переопределить эти методы для подсчета ссылок. Так же как и в С++ smart pointers.
2) (Не самый удобный способ, но иногда очень полезный) Custom variants — компилятор, опять же на основании счетчиков ссылок, гарантирует удаление "ненужных" объектов.
3) Строки и динамические массивы. Хоть и непереопределяемые, но очень часто используемые.
В>>> Но он при этом и на язык высокого уровня особо не претендует, скорее это "переносимый ассемблер". M>>Опять неправильно. С всегда относится к языкам высокого уровня.
В>Официально — да. По сравнению с другими языками высокого уровня — он имеет ну очень низкий уровень.
Тогда надо определиться с терминами.
Здравствуйте, mrhru, Вы писали:
В>>... Потому как отсутствие автоматического уничтожения объектов, наряду с отстутствием какой-либо системы сборки мусора, для современного прикладного языка высокого уровня — просто несерьезно.
M>А в С++ существует какая-либо встроенная система уборки мусора для объектов создаваемых в куче?
А встроенная то зачем, если она реализуема штатными средствами языка? Да и велосипедов, рулящих временем жизни объектов, создаваемых в куче, — предостаточно : std::auto_ptr( ), boost::shared_ptr( ), Loki::SmartPtr( )
Здравствуйте, ssm, Вы писали:
ssm>Здравствуйте, mrhru, Вы писали:
В>>>... Потому как отсутствие автоматического уничтожения объектов, наряду с отстутствием какой-либо системы сборки мусора, для современного прикладного языка высокого уровня — просто несерьезно.
M>>А в С++ существует какая-либо встроенная система уборки мусора для объектов создаваемых в куче?
ssm>А встроенная то зачем, если она реализуема штатными средствами языка? Да и велосипедов, рулящих временем жизни объектов, создаваемых в куче, — предостаточно : std::auto_ptr( ), boost::shared_ptr( ), Loki::SmartPtr( )
Здравствуйте, mrhru, Вы писали:
В>>Начнем с того, что в С нет объектов. Или уточни, что ты понимаешь под объектами (с философской точки зрения это может быть что угодно). M>Прототип объектов в С++ — структуры.
Это лишь прототипы (так же как в паскале — записи). Понятие "разрушения" для структуры в С довольно абстрактно, никаких особых действий (типа вызова деструкторов) не происходит и сам компилятор не пытается что-то такое особенное сделать.
[...] В>>Что неправильно? Необходимость ручного управления ресурсами без возможности хоть как-то автоматизировать их освобождение? Где неправильно? M>В С нет возможности хоть как-то автоматизировать освобождение объектов, в Delphi — есть.
Согласен, что-то в дельфях есть. Но судя по высказываниям в этой же ветке, пользоваться этим не всегда представляется возможным. Те же интерфейсы и Variant были сделаны в угоду удобства работы COM и вынесены на уровень языка. С одной стороны, кстати, дельфи как "язык программирования под винды" крайне привлекателен — многие виндовые заморочки вынесены на уровень языка и работать с ними, естественно, становится удобнее. Но с другой стороны — все эти рулезы остаются "заплатками" и не добавляют стройности самому языку.
Здравствуйте, ssm, Вы писали:
M>>А в С++ существует какая-либо встроенная система уборки мусора для объектов создаваемых в куче? ssm>А встроенная то зачем, если она реализуема штатными средствами языка?
Встроенная удобнее и, как правило, эффективнее.
ssm>Да и велосипедов, рулящих временем жизни объектов, создаваемых в куче, — предостаточно : std::auto_ptr( ), boost::shared_ptr( ), Loki::SmartPtr( )
Это не совсем сборка мусора. Это все вариации на тему автоматического уничтожения объектов. Пример сборщика мусора для С++ можно найти в одной из статей на этом сайте, там все несколько сложнее Насколько я помню, основная "громоздкость" заключалась в "регистрировании" объектов, подлежащих обработке сборщиком мусора.
Здравствуйте, Владик, Вы писали:
В>>>Начнем с того, что в С нет объектов. Или уточни, что ты понимаешь под объектами (с философской точки зрения это может быть что угодно). M>>Прототип объектов в С++ — структуры.
В>Это лишь прототипы (так же как в паскале — записи). Понятие "разрушения" для структуры в С довольно абстрактно, никаких особых действий (типа вызова деструкторов) не происходит и сам компилятор не пытается что-то такое особенное сделать.
Да, согласен. Единственно, налогическом уровне — просто "удобно" так думать, что структуры удаляются. Иначе не избежать проблем при возврате адреса автоматической структуры.
В Delphi же, для структур вызывается код очистки, корректно удаляющий строки, динамические массивы, и вызывающий обработчики для интерфейсов и variant'ов.
В>[...] В>>>Что неправильно? Необходимость ручного управления ресурсами без возможности хоть как-то автоматизировать их освобождение? Где неправильно? M>>В С нет возможности хоть как-то автоматизировать освобождение объектов, в Delphi — есть.
В>Согласен, что-то в дельфях есть.
В>Но судя по высказываниям в этой же ветке, пользоваться этим не всегда представляется возможным. Те же интерфейсы и Variant были сделаны в угоду удобства работы COM и вынесены на уровень языка.
Варианты — да, а интерфейсы были сделаны гораздо позже, чем было реализована поддержка СОМ/OLE.
И сами интерфейсы, как самостоятельная структура языка, очень даже "юзабельны" — как в Java или в C#.
В>С одной стороны, кстати, дельфи как "язык программирования под винды" крайне привлекателен — многие виндовые заморочки вынесены на уровень языка и работать с ними, естественно, становится удобнее. Но с другой стороны — все эти рулезы остаются "заплатками" и не добавляют стройности самому языку.
Здравствуйте, Владик, Вы писали:
В>Встроенная удобнее и, как правило, эффективнее.
И в чем было ее удобство(для С++)?
ssm>>std::auto_ptr( ), boost::shared_ptr( ), Loki::SmartPtr( )
В>Это не совсем сборка мусора.
а я и неговорил этого, я о управлении памятью для объектов сохданых в куче
В>Это все вариации на тему автоматического уничтожения объектов. Пример сборщика мусора для С++ можно найти в одной из статей на этом сайте, там все несколько сложнее Насколько я помню, основная "громоздкость" заключалась в "регистрировании" объектов, подлежащих обработке сборщиком мусора.
IMHO для С++ встроенный сборщик мусора — явное излишество
Здравствуйте, ssm, Вы писали:
ssm>И в чем было ее удобство(для С++)?
Дык. В том, в чем удобство сборщика мусор вообще — за тобой все чистят (когда-нибудь). Хотя конкретно для С++ реализация сборщика мусора представляет скорее академический интерес. На практике вполне хватает упоминавшихся смарт-поинтеров и т.п.
Здравствуйте, Владик, Вы писали:
В>Здравствуйте, s.ts, Вы писали:
ST>>Поддерживаю двумя руками ST>>Тем более, что "ссылочная модель", фактически по возмозможностям является подмножеством множественного наследования + переопределение операторов (С++), но реализована на уровне компилятора.
В>Не понял. Что реализовано на уровне компилятора? И какое отношение ссылочная модель имеет к переопределению операторов?
М.б. я плохо выразился.
Просто в дельфи вызов Release делает компилятор, тогда как в С++ все то же самое реализуется за счет переопределения операции присваивания (непосредственно для класса или для какого-нибудь там SmartPointer-а). Подсчет ссылок в дельфи есть часть языка, а в С++ — реализуется средствами самого языка (в общем, нет в с++ [как в языке] понятия "подсчет ссылок" — это реализуется как часть библиотеки)