Russian Qt Forum

Qt => Общие вопросы => Тема начата: n4ela от Январь 08, 2010, 00:58



Название: Основы удаления объектов
Отправлено: n4ela от Январь 08, 2010, 00:58
Привет всем. Я запутался когда надо удалять созданные объекты самому а когда они удалятся сами.
Вот приведу несколько ситуаций.
1. Я создал класс отнаследовав его от QWidget, в нем объявил и работал с несколькими объектами из qt(например qlabel и qpushbutton), я не переопределал деструктор в своем классе(т.е. его у меня вобще нет ).
При разрушение моего класса qlabel и qpushbutton очистят память?

2. Я создал класс отнаследовав его от QWidget, в нем объявил и работал с несколькими объектами из qt(например qlabel и qpushbutton), я переопределил деструктор и оставил его пустым.
При разрушение моего класса qlabel и qpushbutton очистят память?

3. Я создал класс отнаследовав его от QWidget, в нем объявил и работал с QList <QLabel* > testList. В середине выполнения программы я сделал testList.clear(). Я не переопределил деструктор в своем классе(т.е. его у меня вобще нет )
Память от label'ов очистится после clear(), после разрушения моего класса? не очистится ни когда и у меня не будет возможности добраться до памяти?

4. Я создал класс отнаследовав его от QWidget, в нем объявил и работал с несколькими объектами из qt(например qlabel и qpushbutton) и со сторонними библиотеками, я переопределил деструктор и оставил его пустым.
При разрушении моего класса объекты из qt очистят память, а из сторонних библиотек останутся?

5. Я создал класс отнаследовав его от QWidget, в нем объявил и работал с QList <что нибудь из сторонних библиотек > testList. В середине выполнения программы я сделал testList.clear(). Я не переопределал деструктор в своем классе(т.е. его у меня вобще нет )
Память не очистится ни когда и после clear у меня не будет возможности очистить память?

6. Я создал класс отнаследовав его от QWidget, в нем объявил и работал с несколькими объектами из qt(например qlabel и qpushbutton), я переопределил деструктор в своем классе и удалил все объекты с помощью delete
Я сделал лишнюю работу но не чего плохого не случится?


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 08, 2010, 01:10
Тебе хорошо бы почитать книжки по с++
Когда ты удаляешь QObject или его наследника, он удалит объекты, яляющиеся дочерними (то есть теми, для которых указан parent)
QWidget * main = new QWidget;
QLabel * lb = new QLabel(main);
QPushButton * button = new QPushButton;
delete main; // удалит main и lb, но НЕ button
Деструктор не переопределяется. Он реализовывается. Более того, ВСЕГДА есть деструктор по умолчанию. Написание ~MyClass() {} не меняет ничего. Ну вообще ничего - ты заменил дефолтный пустой деструктор своим пустым деструктором
Потому пункт 1 и 2 это одно и то же
3) clear не вызывает delete. Оно очищает список. Что было бы если бы у тебя было 2 списка? есть макрос qDeleteAll, но он НЕ вызывает clear()
4) удалятся только объекты с указанным родителем
5) да
6) да, можно и так сказать


Название: Re: Основы удаление объектов.
Отправлено: SABROG от Январь 08, 2010, 01:11
Это же проверяется быстрей, чем ты писал свой пост, сигнал

void QObject::destroyed ( QObject * obj = 0 )


Название: Re: Основы удаление объектов.
Отправлено: Геннадий Пастухов от Январь 08, 2010, 01:16
Привет всем. Я запутался когда надо удалять созданные объекты самому а когда они удалятся сами.

Общее правило стандартное С++-ное: автоматические объекты удалятся сами, созданные вручную через new необходимо удалять самому.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 01:28
Общее правило стандартное С++-ное: автоматические объекты удалятся сами, созданные вручную через new необходимо удалять самому.

Во-первых, что такое "автоматические обьекты"? Во-вторых не вижу связи, что выделенное через new нужно удалять самому. Qt наглядно демонстрирует, что это не так. К примеру QObject сам удалит дочерние обьекты, а QSharedDataPointer сам удалит руками выделенный экземпляр QSharedData.


Название: Re: Основы удаление объектов.
Отправлено: n4ela от Январь 08, 2010, 01:50
Общее правило стандартное С++-ное: автоматические объекты удалятся сами, созданные вручную через new необходимо удалять самому.
Как раз таки это меня и запутало, во всех книжках про qt написано, что дочерние объекты удалятся сами при уничтожения родителя. Вот сейчас просто решил уточнить, правильно ли я это понимаю, что уже знать наверняка.


Когда ты удаляешь QObject или его наследника, он удалит объекты, яляющиеся дочерними (то есть теми, для которых указан parent)
QWidget * main = new QWidget;
QLabel * lb = new QLabel(main);
QPushButton * button = new QPushButton;
delete main; // удалит main и lb, но НЕ button
Вот тут опять не понятно, приведу пример:
form.h
Код
C++ (Qt)
class Form : public QWidget
{
   Q_OBJECT
 
public:
   Form( QWidget *parent = 0 );
   ~Form();
 
private:
   QLineEdit *line;
   QPushButton *button;
};
#endif
form.cpp
Код
C++ (Qt)
Form::Form( QWidget *parent )
   :QWidget( parent )
{
   line = new QLineEdit( this )
   button = new QPushButton;
   QPushButton *testButton = new QPushButton;
}
 
main.cpp
Код
C++ (Qt)
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   Form w;
   w.show();
   return a.exec();
}

По вашему примеру получается что button и testButton не удалятся


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 02:53
По вашему примеру получается что button и testButton не удалятся

Именно. А почему они должны удалиться?


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 06:55
Во-первых, что такое "автоматические обьекты"?
Автоматическими называются объекты созданные в стеке. Момент их создания, их количество и время уничтожения заранее известны компилятору, и он полностью отвечает за их жизненный цикл. Отсюда и название  - автоматические (вполне официальное; в стандарте есть даже ключевое слово auto).
Во-вторых не вижу связи, что выделенное через new нужно удалять самому. Qt наглядно демонстрирует, что это не так. К примеру QObject сам удалит дочерние обьекты, а QSharedDataPointer сам удалит руками выделенный экземпляр QSharedData.
В общем случае - да, удалять самому. Компилятор не контролирует ни создание динамических объектов, ни их уничтожение. QObject удалить свои дочерние объекты только в том случае, если вы при их создании явно укажите, что они его дочерние объекты, передав в конструкторе указатель на родителя. Именно поэтому в примере из предпоследнего поста button и testButton не удаляются при уничтожении экземпляра Form (форма не считает их дочерними). Так что это архитектурная особенность библиотеки, а не правило языка.

Как раз таки это меня и запутало, во всех книжках про qt написано, что дочерние объекты удалятся сами при уничтожения родителя. Вот сейчас просто решил уточнить, правильно ли я это понимаю, что уже знать наверняка.
Все так, но, как я уже написал выше, родственную связь нужно описывать явно, передавая указатель на родителя. Иначе никакой зачистки памяти не будет.
При использовании layout-ов указатель на родителя можно не передавать, посколько layout берет эту часть работы на себя.


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 07:12
Цитировать
Автоматическими называются объекты созданные в стеке.
именно в стеке!
а создание объекта при помощи new отменяет любую "автоматику".

Цитировать
в стандарте есть даже ключевое слово auto
да, но назначение это КС совсем иное ;)

Цитировать
QObject удалить свои дочерние объекты только в том случае, если вы при их создании явно укажите, что они его дочерние объекты, передав в конструкторе указатель на родителя.
уже отвечал: http://www.prog.org.ru/index.php?topic=11965.msg75045#msg75045

Цитировать
Так что это архитектурная особенность библиотеки, а не правило языка.
в данном контексте да.



Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 07:23
Так что это архитектурная особенность библиотеки, а не правило языка.

Собственно, автор и спрашивал про архитектурную особенность библиотеки. А правила языка думаю и так все знают. В Qt3 помимо QList, QDict и прочих были классы QPtrList, QPtrDict, которые действительно делали то, что спрашивается автор - удаляли данные по указателям. В Qt4 же их упразднили, теперь контейнеры занимаются только хранением указателей, никакого неявного выделения/удаления памяти они не делают.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 07:32
Цитировать
в стандарте есть даже ключевое слово auto
да, но назначение это КС совсем иное ;)
Пока я понимаю так: Автоматические переменные автоматически создаются в стеке при входе в область видимости и автоматически уничтожаются при выходе из нее. На это обстоятельство можно указать явно, используя ключевое слово auto. Поскольку все локальные переменные являются автоматическими по умолчанию, то данное КС на практике не применяют (по крайней мере я не видел), а в язык оно включено для полноты.

Если вам известны другие значения КС auto, поделитесь пожалуйста.


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 07:44
Цитировать
Пока я понимаю так: Автоматические переменные автоматически создаются в стеке при входе в область видимости и автоматически уничтожаются при выходе из нее.
верно.

Цитировать
На это обстоятельство можно указать явно, используя ключевое слово auto.
абсолютно не верно!
у этого КС, иной, гораздо более необходимый смысл.

Цитировать
Поскольку все локальные переменные являются автоматическими по умолчанию, то данное КС на практике не применяют (по крайней мере я не видел), а в язык оно включено для полноты.
никому этого не говори ;D засмеют и заплюют.

вот: http://en.wikipedia.org/wiki/C%2B%2B0x#Type_inference


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 09:11
у этого КС, иной, гораздо более необходимый смысл.

Цитировать
Поскольку все локальные переменные являются автоматическими по умолчанию, то данное КС на практике не применяют (по крайней мере я не видел), а в язык оно включено для полноты.
никому этого не говори ;D засмеют и заплюют.

вот: http://en.wikipedia.org/wiki/C%2B%2B0x#Type_inference
Приведенная тобой ссылка относится к новому еще разрабатываемому стандарту С++0x. Там явно указано, что использование КС auto в таком контексте относится к усовершенствованию ядра языка. Это значит в действующем стандарте ничего подобно нету. Я же имел ввиду действующую сейчас редакцию C++03. И когда говорил, что я не видел на практике примеров применения, я имел ввиду исходные тексты рабочих программ.

Я не считаю себя опытным программистом на С++, поэтому многое могу не знать. Но нигде в литературе др. применения auto я тоже не встречал. Если кто знает, то прошу поделиться. Мне это действительно интересно. Форум на то и нужен, чтобы общаться и делиться знаниями.

P.S. спасибо за ссылку niXman, почитаю на досуге  :)


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 09:22
Цитировать
Приведенная тобой ссылка относится к новому еще разрабатываемому стандарту С++0x.
конечно, с++0х еще разрабатываемый, но для меня он основным, уже как пол года. в версии gcc-4.5 появится поддержка лямбда, вот тогда, он будет реализован на 97%.
а про то, древнее КС auto, я не подумал, из-за того, что оно ваще не понятно для чего существует. так как модель памяти по умолчанию автоматическая.

Цитировать
Если кто знает, то прошу поделиться.
по приведенной мною ссылке, внизу страницы, куча доки на эту тему.


Название: Re: Основы удаление объектов.
Отправлено: Геннадий Пастухов от Январь 08, 2010, 13:27
Общее правило стандартное С++-ное: автоматические объекты удалятся сами, созданные вручную через new необходимо удалять самому.

Во-первых, что такое "автоматические обьекты"? Во-вторых не вижу связи, что выделенное через new нужно удалять самому. Qt наглядно демонстрирует, что это не так. К примеру QObject сам удалит дочерние обьекты, а QSharedDataPointer сам удалит руками выделенный экземпляр QSharedData.

Про объекты уже написали, а про создание/удаление в любом варианте С++ лучше не заниматься самодеятельностью, а всегда автоматически делать: создал объект через new - удали его через delete. Лень этим заниматься - используй auto_ptr. Лень самому заниматься обработкой памяти - используй только автоматические объекты. Но никогда не оставляй ничего не самотек, иначе получишь как раз утёк памяти :) В программе, которая 1 раз запускается и тут же завершается - это, возможно, роли не сыграет, но если она будет работать хотя бы несколько минут - последствия будут самыми плачевными. Контроль за памятью убережёт тебя от кучи странных ошибок, поэтому сразу привыкай следить за ней самым тщательным образом.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 13:50
Геннадий Пастухов, такое ощущение, что вы пришли из мира C, для него ваши замечания справедливы (с единственной поправкой на auto_ptr). Для C++ же существуют виртуальные деструкторы и множество вариантов шаблонов, позволяющие на N вызовов new в разных кусках кода иметь всего один delete. Про самодеятельность - это вы мимо. Степень потенциальных ошибок в C++ как раз пропорциональна количеству явных вызовов delete в коде.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 14:24
Для C++ же существуют виртуальные деструкторы и множество вариантов шаблонов, позволяющие на N вызовов new в разных кусках кода иметь всего один delete. Про самодеятельность - это вы мимо.

 :o причем здесь виртуальные деструкторы??

можно поподробнее про шаблоны, позволяющие на N вызовов new делать один delete (примерчик желательно)?

Степень потенциальных ошибок в C++ как раз пропорциональна количеству явных вызовов delete в коде.

Ничего подобного. Главное не оставлять висячих указатель:
Код:
MyClass* p = new MyClass;
...
//do something
...
delete p;
p = 0;
...
if(p){
//действия с объектом через указатель
}
delete p;//p == 0, ничего не случится


Название: Re: Основы удаление объектов.
Отправлено: Геннадий Пастухов от Январь 08, 2010, 14:34
Геннадий Пастухов, такое ощущение, что вы пришли из мира C, для него ваши замечания справедливы (с единственной поправкой на auto_ptr). Для C++ же существуют виртуальные деструкторы и множество вариантов шаблонов, позволяющие на N вызовов new в разных кусках кода иметь всего один delete. Про самодеятельность - это вы мимо. Степень потенциальных ошибок в C++ как раз пропорциональна количеству явных вызовов delete в коде.

Ну история моя была несколько иной, начинал я с С++, потом уже был С, а потом опять С++. По следующему предложению: какое отношению к контролю памяти имеют виртуальные деструкторы? О каких шаблонах идёт речь, о template? Какое отношение они имеют к связке new/delete? Ты имеешь в виду, что, допустим, есть template list, который при помещении в него объектов делает new для каждого из них, а потом все их махом мы удаляем путем delete объекта шаблона? Это ровно то, о чём я писал - в этом случае delete будет делаться деструктором шаблона и количество new/delete будет равным.

Про количество вызовов delete тоже не совсем ясно, ты про вариант, когда мы удаляем объект, созданный не через new?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 14:36
причем здесь виртуальные деструкторы??

А зачем вообще придумали виртуальные деструкторы? Ответом на этот вопрос будет и ответ на ваш.

можно поподробнее про шаблоны, позволяющие на N вызовов new делать один delete (примерчик желательно)?

Загляните в исходник того же QSharedDataPointer.

Ничего подобного. Главное не оставлять висячих указатель:

"Если бы всё было так просто всё не было бы так сложно" (с) О том и речь, что инструмент должен защищать программиста от случайных ошибок, а не говорить "сам дурак, оставил висячий указатель".


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 08, 2010, 14:39
#define delete(p) delete p; p = 0;


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 14:44
Геннадий Пастухов, вас немного не туда занесло. Программы пишутся для человека, а не для машины. Речь идёт о количестве записей new/delete в коде, а не о количестве их вызовов во время выполнения.


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 14:48
Геннадий Пастухов, такое ощущение, что вы пришли из мира C, для него ваши замечания справедливы (с единственной поправкой на auto_ptr). Для C++ же существуют виртуальные деструкторы и множество вариантов шаблонов, позволяющие на N вызовов new в разных кусках кода иметь всего один delete. Про самодеятельность - это вы мимо. Степень потенциальных ошибок в C++ как раз пропорциональна количеству явных вызовов delete в коде.
Я не считаю С "дурным тоном". И, конечно, контейнеры, шаблоны - дело великое и экономят массу времени. Но они тоже не идеальны. Например

Код:
QList <int> lst;
for (int i = 0; i < 1024 * 1024; ++i)
 lst.append(i);
...
lst.clear();  // это не освободит память

Так что иной раз и незатейливое new лучше. И согласен с Геннадием что delete должно делаться учитываться программистом "рефлекторно" на каждое new. И лучше освоить это твердо до прикручивания высокоуровневых классов а то "каша" получится.


Название: Re: Основы удаление объектов.
Отправлено: lit-uriy от Январь 08, 2010, 15:01
>>И согласен с Геннадием что delete должно делаться программистом "рефлекторно" на каждое new.
этот рефлекс может породить проблемы в Qt, при работе с наследниками QObject.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 15:01
И согласен с Геннадием что delete должно делаться программистом "рефлекторно" на каждое new.

Вы всё перепутали. На каждое new программист должен delete иметь в виду, а не писать явно в коде. Каким образом этот delete будет вызван во время выполнения - вопрос десятый, определяется не без чтения документации по используемому инструментарию. В основном это: 1) шаблоны, 2) виртуальные деструкторы и 3) явный delete, наличие которых в программе должно быть сведено к минимуму.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 15:19
причем здесь виртуальные деструкторы??

А зачем вообще придумали виртуальные деструкторы? Ответом на этот вопрос будет и ответ на ваш.

а я его не случайно задал.. Виртуальные деструкторы нужны в полиморфной иерархии, чтобы при работе с указателем на базовый объект вызывался деструктор не базового объекта, а именно того фактического объекта, на который данный указатель ссылается (на один new имеем один delete). Как это связывается с вашей фразой
Для C++ же существуют виртуальные деструкторы и множество вариантов шаблонов, позволяющие на N вызовов new в разных кусках кода иметь всего один delete.
от меня ускользает...


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 15:25
ilot, http://www.prog.org.ru/index.php?topic=11963.msg75091#msg75091


Название: Re: Основы удаление объектов.
Отправлено: Геннадий Пастухов от Январь 08, 2010, 15:30
И согласен с Геннадием что delete должно делаться программистом "рефлекторно" на каждое new.

Вы всё перепутали. На каждое new программист должен delete иметь в виду, а не писать явно в коде. Каким образом этот delete будет вызван во время выполнения - вопрос десятый, определяется не без чтения документации по используемому инструментарию. В основном это: 1) шаблоны, 2) виртуальные деструкторы и 3) явный delete, наличие которых в программе должно быть сведено к минимуму.

Ну мы уже вдвоём просим пример, когда new в коде есть, а delete - нет, и при этом память корректно освобождается!


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 15:35
ilot, http://www.prog.org.ru/index.php?topic=11963.msg75091#msg75091
кхе..кхе. Вы просто рушите мое мировоззрение.. :) И как же наличие виртуального деструктора позволит сократить количество вызовов delete в программе??

Ну мы уже вдвоём просим пример, когда new в коде есть, а delete - нет, и при этом память корректно освобождается!

Ну почему же, я тоже хотел бы посмотреть..


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 15:36
Код
C++ (Qt)
int main( int argc, char ** argv )
{
   QApplication app( argc, argv );
   QWidget widget;
   new QLabel( &widget ); // here
   widget.show();
   return app.exec();
}
 

Количество в коде new одно, количество в коде delete ноль.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 15:39
И как же наличие виртуального деструктора позволит сократить количество вызовов delete в программе??

> вызовов

Как будто специально не читаете.

Речь идёт о количестве записей new/delete в коде, а не о количестве их вызовов во время выполнения.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 15:43
> вызовов

Как будто специально не читаете.
переформулирую вопрос:
И как же наличие виртуального деструктора позволит сократить количество записей delete в программе??



Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 15:45
На один пост выше.


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 15:46
>>И согласен с Геннадием что delete должно делаться программистом "рефлекторно" на каждое new.
этот рефлекс может породить проблемы в Qt, при работе с наследниками QObject.
Есть правила, есть исключения. Но исключения не значат что можно обойтись без правил.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 15:52
Код
C++ (Qt)
int main( int argc, char ** argv )
{
   QApplication app( argc, argv );
   QWidget widget;
   new QLabel( &widget ); // here
   widget.show();
   return app.exec();
}
 
да, приходится учитывать особенности фреймфорка, с которым работаешь. Но здесь еще вопрос что лучше: запомнить раз и навсегда, что для каждого new должна выполняться зачистка, либо запоминать в каких случаях библиотека все сделает за тебя, а когда нужно вызывать деструктор самому (и так для каждой библиотеки, а их довольно много). ИМХО, если приоритетным выбирать 2-й вариант действий, то напортачить гораздо проще и найти ошибку сложнее будет.

На один пост выше.
причем здесь виртуальный деструктор ?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 08, 2010, 16:21
Есть стандарт C++, виртуальные деструкторы и шаблоны - часть этого стандарта. Фреймфорк, в данном случае Qt, ни на шаг не отклоняется от семантики использования этих возможностей. Правила на 100% определяются документацией к классам библиотеки. Каждый вызов метода и каждый подставляемый в этот метод параметр строго определяют действие, которое будет выполнено. И если документация к методу гласит, что деструктор будет вызван автоматически - так оно и будет. Любое отклонение от этих правил и есть та самая самодеятельность, влекущая ошибки, ибо вы сами не поймёте через время зачем написали так, когда библиотека подразумевает делать иначе.

Что касается new/delete в коде. Идеальная программа - в которой нет ни одного явного вызова delete вообще.

причем здесь виртуальный деструктор ?

Пусть это будет вам задание на дом.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 08, 2010, 16:51
мой вопрос, повторяемый из сообщения в сообщение:
Цитировать
причем здесь виртуальный деструктор??

ваши ответы:
Цитировать
А зачем вообще придумали виртуальные деструкторы? Ответом на этот вопрос будет и ответ на ваш.
Цитировать
ilot, http://www.prog.org.ru/index.php?topic=11963.msg75091#msg75091
ссылающийся на:
Программы пишутся для человека, а не для машины. Речь идёт о количестве записей new/delete в коде, а не о количестве их вызовов во время выполнения.
> вызовов

Как будто специально не читаете.
На один пост выше.
(причем здесь этот пост?)
и в завершение
Пусть это будет вам задание на дом.

;D

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


Название: Re: Основы удаление объектов.
Отправлено: Геннадий Пастухов от Январь 08, 2010, 17:00
Код
C++ (Qt)
int main( int argc, char ** argv )
{
   QApplication app( argc, argv );
   QWidget widget;
   new QLabel( &widget ); // here
   widget.show();
   return app.exec();
}
 

Количество в коде new одно, количество в коде delete ноль.

Совершенно верно, и при этом моим словам это не противоречит. Ты привёл пример создания иерархии объектов, в которой за очисткой памяти следит фреймворк. Когда же мы создаём одиночный объект, то не важно, чей он потомок, сам собой он удалится только в одном случае - при всё том же вызове деструктора. И, в общем случае, это произойдёт при завершении работы программы. Так что помнить об этом нужно непременно.

Ну и, строки вида
Код
C++ (Qt)
new QLabel( &widget ); // here
, конечно, вполне корректны с точки зрения Qt, но с точки зрения С++ нехорошо смотрятся :) Я бы всё-таки написал
Код
C++ (Qt)
QLabel lbl = new QLabel( &widget ); // here
, ведь мы, всё же, используем С++, и, думаю, лучше всегда пользоваться его соглашениями при оформлении кода.


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 18:47
детский сад, честное слово...

ilot, именно вам я давал ссылки по теме. повторю:
1. http://ru.wikipedia.org/wiki/Абстрактная_фабрика_(шаблон_проектирования)
2. http://ru.wikipedia.org/wiki/Строитель_(шаблон_проектирования)
3. http://ru.wikipedia.org/wiki/Одиночка_(шаблон_проектирования)
эти три паттерна, плюс принцип RAII(http://ru.wikipedia.org/wiki/RAII), избавляют программиста от головной боли и утечек памяти.

так же по теме, что будет как минимум полезно, еще это порекомендую:
http://ru.wikipedia.org/wiki/Объектный_пул
http://ru.wikipedia.org/wiki/Прототип_(шаблон_проектирования)

а еще лучше, прочесть всю тему:
http://ru.wikipedia.org/wiki/Шаблоны_проектирования

кто напишет wiki?


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 20:39
детский сад, честное слово...

ilot, именно вам я давал ссылки по теме. повторю:
...
так же по теме, что будет как минимум полезно, еще это порекомендую:
...
а еще лучше, прочесть всю тему:
...
niXman. я против Вас ничего не имею, но мне кажется, что детский сад - это те ссылки которые Вы даете  :)
Да, слова там везде хорошие и правильные и они от реальной практики. Только вот применимо это все в одном случае - "за спиной" мощного инструментария (типа Qt) который делает 80% того что требуется. Вот тогда очень хорошо/удобно покалякать о "концепциях", "сущностях" и.т.п.

Но все это проходит "как с белых яблонь дым" как только выйти за рамки стандартных задач. Попробуйте напр. написать просто ListBox "с нуля", т.е. используя только ф-ции рисования и базовые events (мне приходилось и не потому что хотел) - и уверяю Вас, от книжной идейности останутся "рожки да ножки". И Вам уже будет не до менторского "порекомендую" - а чтобы оно "абы как но работало".

ilot и Геннадий правильно поясняют что есть "основы" которыми нужно владеть в полной мере. А нахвататься умных классов библиотеки - там и помогать не надо  :)


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 08, 2010, 20:49
Итак посмотрим что тут у нас:
widget.h
Код:
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class QTextEdit;
class QComboBox;

class widget:public QWidget
{
    Q_OBJECT
public:
    widget(QWidget *parent=0);
    ~widget();
    QTextEdit *text;
    QComboBox *combo;

private slots:
    void crash();
};

#endif // WIDGET_H

widget.cpp
Код:
#include <QtGui>
#include "widget.h"

widget::widget(QWidget *parent):QWidget(parent)
{
    text=new QTextEdit(this);
    combo=new QComboBox(this);
    qDebug()<<connect(text,SIGNAL(destroyed()),this,SLOT(crash()));
    qDebug()<<connect(combo,SIGNAL(destroyed()),this,SLOT(crash()));
}

void widget::crash()
{
    static int num=0;
    qDebug()<<"Crashed number "+QString::number(num);
    ++num;
}

widget::~widget()
{
    qDebug()<<"Widget Crashed!";
}

main.cpp
Код:
#include <QtGui>
#include "widget.h"

int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    widget w;
    w.show();
    app.exec();
    return 0;
}

Компилируем программу и опа..объект widget удаляется, а его дочерние объекты нет! Хотя заданы явно..
Цитировать
text=new QTextEdit(this);
    combo=new QComboBox(this);

В деструктор widget добавляем, например delete text; и на консоль выводится нужное "Crashed number 0"..
Господа, что же это значит? Я так понимаю, что не стоит надеяться на фрэймворк и явно вызывать delete, как это принято в стандарте C++..есть другие мнения?


Название: Re: Основы удаление объектов.
Отправлено: BRE от Январь 08, 2010, 21:02
В деструктор widget добавляем, например delete text; и на консоль выводится нужное "Crashed number 0"..
Господа, что же это значит? Я так понимаю, что не стоит надеяться на фрэймворк и явно вызывать delete, как это принято в стандарте C++..есть другие мнения?
Можно и явно вызывать, при разрушение дочерний уберет себя из списка в родительском виджете.

Или измени код например так:
main.cpp
Код
C++ (Qt)
#include <QtGui>
#include "widget.h"
 
int main(int argc,char* argv[])
{
   QApplication app(argc,argv);
   widget *w = new widget;
   w->show();
   app.exec();
   delete w;
   return 0;
}
 

Кстати, можно писать просто:
Код
C++ (Qt)
   qDebug() << "Crashed number " << num;
 


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 21:04
Цитировать
"за спиной" мощного инструментария (типа Qt) который делает 80% того что требуется.
тогда о чем речь? о непонимании концепции Qt? или общего непонимания стратегии проектирования приложения?

Цитировать
Попробуйте напр. написать просто ListBox "с нуля"
могу попробовать(уже пробовал и не раз) что-то другое, алгоритмичное. просто не люблю ГУЙ писать :)

Цитировать
И Вам уже будет не до менторского "порекомендую" - а чтобы оно "абы как но работало".
тут я с вами не соглашусь!
я сторонник "идеального" кода. и если есть два способа реализовать задачу, при том один простой, другой правильный - я выберу второй. даже если для этого придется написать в пять раз больше кода.

Цитировать
А нахвататься умных классов библиотеки - там и помогать не надо
в данном случае это относится к Qt.

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


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 08, 2010, 21:10
BRE, изменил код как сказали, удаления дочерних объектов не произошло..короче нафиг эти иерархии объектов, что-то непонятное с ними (либо я чего-то не понимаю)..Может кто-нибудь скажет как в приведенном мною коде все правильно организовать, чтобы widget удалял дочерние объекты автоматически?


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 21:15
В деструктор widget добавляем, например delete text; и на консоль выводится нужное "Crashed number 0"..
Господа, что же это значит? Я так понимаю, что не стоит надеяться на фрэймворк и явно вызывать delete, как это принято в стандарте C++..есть другие мнения?
Это не тот вопрос который решается мнением/голосованием  :)  Выложите пожалуйста компилябельный проект, попробуем разобраться. Все children должны быть удалены parent'ом, Qt это гарантирует. Нельзя удалять что уже удалено


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 08, 2010, 21:18
http://rghost.ru/806868 вот проект..


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 21:24
обдумав все, переварив, выделил два момента, которые как мне кажется, являются основными для понимания и разрешения вопроса.
1. не понимание концепции фреймворков, и непонимание концепции Qt в часности.
2. при проектировании более не менее сложного проекта, нужно сначала набросать его структуру(UML поможет). и при проектировании ОО реализации, нужно вложить в проект "здравый" смысл в плане реализации родства объектов. тут и появляется возможность полностью избавить себя от управления памятью(пул объектов + абстрактная фабрика + синглтон). но если хочется по проще, то пул объектов можно исключить.

зы
в чем изъян? ;)


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 08, 2010, 21:27
надо было написать еще на 2й странице. Вы удаляете объект ПОСЛЕ выхода из цикла обработки событий. Как следствие никакие сигналы/слоты уже не работают. Да, объекты удаляются, да destroyed() вызывается, но никаких коннектов к нему уже нет. Потому печати и нет. Отнаследуйтесь от обектов, определите деструктор с отладочной печатью и будет вам счастье


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 21:33
могу попробовать(уже пробовал и не раз) что-то другое, алгоритмичное. просто не люблю ГУЙ писать :)
Представьте себе - я тоже  :) Работы с алгоритмами у меня валом. Вот только проблемы с работниками - все хотят делать UI, web и.т.п. в общем, то что выучили. а если надо думать своей головой - так сразу в кусты  :'( Спишемся в личке?


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 08, 2010, 21:34
а че делать надо?) а то у меня валом работы где надо учить кучу нового:( из разряда 2 недели гугла - 1 строчка решения) если алгоритмы, то это хорошо)


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 21:43
Цитировать
все хотят делать UI, web и.т.п.
это временно.
я тоже когда маленький был, хотел гуй писать. но как оказалось, это скука смертная :(


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 08, 2010, 21:54
Спасибо Авварону за ответ - все правильно! Теперь другой вопрос, отображается ли освобождение памяти в виндовском диспетчере задач? Память там только увеличивается..


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 21:58
Цитировать
отображается ли освобождение памяти в виндовском диспетчере задач?
какое отношение этот вопрос имеет к Qt?


Название: Re: Основы удаление объектов.
Отправлено: BRE от Январь 08, 2010, 21:58
Спасибо Авварону за ответ - все правильно! Теперь другой вопрос, отображается ли освобождение памяти в виндовском диспетчере задач? Память там только увеличивается..
Не мониторь память по вендовому диспетчеру, он немного другую память показывает. Память отдается и приложение может ей пользоваться.


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 22:02
Цитировать
все хотят делать UI, web и.т.п.
это временно.
я тоже когда маленький был, хотел гуй писать. но как оказалось, это скука смертная :(
Ну почему "был"  :) :)


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 08, 2010, 22:03
niXman, я не писал что этот вопрос имеет отношение к Qt..


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 08, 2010, 22:14
а че делать надо?) а то у меня валом работы где надо учить кучу нового:( из разряда 2 недели гугла - 1 строчка решения) если алгоритмы, то это хорошо)
Понимаю, но с алгоритмами никак не слаще. В чисто технических вещах - они хоть имеют конкретное решение (переписать тупой текст типа AECoerseDesc и.т.п), ладно, перетерпеть можно.  А с алгоритмами  - прочтешь пяток Phd где уверяется что, дескать, эта проблема полностью рассмотрена и решена, примешь 500-700, скажешь нехорошие слова о мамах этих теоретиков - и на следующий день по новой.


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 08, 2010, 22:27
Цитировать
Ну почему "был"
потому что мой возраст, ну ни как не назовешь детством ;)

Цитировать
я не писал что этот вопрос имеет отношение к Qt..
а тематика сего форума, вам известна?


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 08, 2010, 22:35
Igors
ну одно дело тупо гуглить, а второе думать.


Название: Re: Основы удаление объектов.
Отправлено: Геннадий Пастухов от Январь 08, 2010, 22:49
Цитировать
все хотят делать UI, web и.т.п.
это временно.
я тоже когда маленький был, хотел гуй писать. но как оказалось, это скука смертная :(


Странно, как можно хотеть писать гуй :) Это ж тоска зелёная... Когда я понял, что такое stdin и stdout - судьба гуя для меня была решена :)


Название: Re: Основы удаление объектов.
Отправлено: BRE от Январь 08, 2010, 22:51
Вы удаляете объект ПОСЛЕ выхода из цикла обработки событий. Как следствие никакие сигналы/слоты уже не работают. Да, объекты удаляются, да destroyed() вызывается, но никаких коннектов к нему уже нет.
Уточню. Никакого значения не имеет то, что цикл обработки событий уже остановлен. Тип соединения сигналов со слотами - DirectConnection, т.е. очередь сообщения не используется. А не вызываются слоты потому, что слоты находятся в удаляемом виджете, поэтому еще до разрушения детей все сигналы с ним разрываются (disconnect).
Если сделать внешний объект, который будет следить за этими сигналами, то все будет работать:
Код
C++ (Qt)
#include <QApplication>          
#include <QLabel>                
#include <QDebug>                
 
class Logger : public QObject
{                            
       Q_OBJECT            
 
public slots:
       void    dead( QObject *obj )
       {
               qDebug() << "Dead object" << obj;
       }
};
 
class TestWidget : public QWidget
{
       Q_OBJECT
public:
       TestWidget( Logger *log ) : QWidget( 0 )
       {
               QLabel *lbl1 = new QLabel( this );
               QLabel *lbl2 = new QLabel( this );
 
               connect( lbl1, SIGNAL( destroyed( QObject * ) ), log, SLOT( dead( QObject * ) ) );
               connect( lbl2, SIGNAL( destroyed( QObject * ) ), log, SLOT( dead( QObject * ) ) );
       }
};
 
int main( int argc, char *argv[] )
{
       QApplication app( argc, argv );
 
       Logger log;
 
       TestWidget *w = new TestWidget( &log );
       w->show();
       app.exec();
       delete w;
 
       return 0;
}
 
#include "main.moc"
 


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 08, 2010, 23:00
Цитировать
я тоже когда маленький был, хотел гуй писать. но как оказалось, это скука смертная

Цитировать
потому что мой возраст, ну ни как не назовешь детством

niXman, из вас прям-таки прет тематика Qt..


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 09, 2010, 00:10
kibsoft, а вы в Qt видите только гуй?  :o
ну...учитесь батенька ;)


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 09, 2010, 00:43
Причем тут GUI..Вы мне говорите что я тут не по теме пишу на форуме, а я вам доказываю, что вы тоже не туда клоните..


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 02:28
А не вызываются слоты потому, что слоты находятся в удаляемом виджете, поэтому еще до разрушения детей все сигналы с ним разрываются (disconnect).

Бзззз! Ответ неверен.

kibsoft, внимание, отвечает Александр Друзь.

1. На вопрос удаляются ли дочерние виджеты, ответ - да, удаляются.
2. На вопрос почему не вызывается слот crash(), ответ - не потому что соединение было разорвано.
3. На вопрос "а почему тогда?" ответ кроется в недрах C++.

Qt использует виртуальные методы для вызова методов по имени (сигналов и слотов). А как мы знаем из теории - виртуальные методы в деструкторах не работают, поскольку отнаследованный обьект (ваш Widget) был разрушен до базового (QObject). Именно в деструкторе QObject удаляюся дочерние обьекты, сигналы destroyed() от которых уже не могут вызвать виртуальный метод в Widget.


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 09, 2010, 02:36
интриги, скандалы, расследования...


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 02:41
Я знаю для чего нужны виртуальные деструкторы и выше написал об этом. Концепция виртуальных деструкторов не имеет никакого отношения к автоматическому удалению объектов, поэтому мне так и не понятно для чего вы прилепили их в общую кучу к шаблонам и неявным вызовам delete, выполняемых фреймворком.

Вы меня запутали. В этой фразе вы сами себе противоречите. С одной стороны вы говорите, что знаете зачем нужны виртуальные деструкторы, и тут же утверждаете, что к автоматическому удалению они отношения не имеют. И что в приведённом мной тривиальном примере виртуальные деструкторы якобы не играют никакой роли. Вы уж определитесь, знаете ли вы таки зачем нужны виртуальные деструкторы. Как тогда QObject автоматически удаляет своё дочернее дерево обьектов, которым он установлен как parent?

Может вы всё ещё думаете, что под автоматическим удалением подразумевается выход из области видимости? Ну так мы же не о терминах спорим. Вопрос изначально стоял по другому: "Как виртуальные деструкторы помогают избежать явного вызова delete в коде."


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 02:56
Ну и, строки вида
Код
C++ (Qt)
new QLabel( &widget ); // here
, конечно, вполне корректны с точки зрения Qt, но с точки зрения С++ нехорошо смотрятся :) Я бы всё-таки написал
Код
C++ (Qt)
QLabel lbl = new QLabel( &widget ); // here
, ведь мы, всё же, используем С++, и, думаю, лучше всегда пользоваться его соглашениями при оформлении кода.

Qt - и есть C++, всё что корректно с точки зрения Qt - корректно и с точки зрения C++. А приведённый пример, как написали бы вы, именно что некорректен что точки зрения C++, поскольку lbl больше нигде не используется в коде, о чём компилятор выдаст предупреждение. Если вы подразумевали под lbl некий экземпляр шаблона (неясно, ибо у вас ошибка в коде, пропущен знак указателя) - то логически он там быть не может, поскольку время жизни lbl не ограничено областью видимости.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 07:24
С одной стороны вы говорите, что знаете зачем нужны виртуальные деструкторы, и тут же утверждаете, что к автоматическому удалению они отношения не имеют. И что в приведённом мной тривиальном примере виртуальные деструкторы якобы не играют никакой роли. Вы уж определитесь, знаете ли вы таки зачем нужны виртуальные деструкторы. Как тогда QObject автоматически удаляет своё дочернее дерево обьектов, которым он установлен как parent?
Код из QObject, который отвечает за удаление потомков:
Код:
QObject::~QObject()
{
    .....
    if (!d->children.isEmpty())
        d->deleteChildren();

    qt_removeObject(this);
    .....
}

void QObjectPrivate::deleteChildren()
{
    const bool reallyWasDeleted = wasDeleted;
    wasDeleted = true;
    // delete children objects
    // don't use qDeleteAll as the destructor of the child might
    // delete siblings
    for (int i = 0; i < children.count(); ++i) {
        currentChildBeingDeleted = children.at(i);
        children[i] = 0;
        delete currentChildBeingDeleted;
    }
    children.clear();
    currentChildBeingDeleted = 0;
    wasDeleted = reallyWasDeleted;
}
Каждый наследник QObject хранит список указателей на собственных потомков. Деструкторы производных классов завершают свою работу вызовом деструктора базового класса. Так, проходя всю цепочку наследования, в конечном итоге вызывается деструктор ~QObject(). В деструкторе ~OObject() проверяется наличие потомков, и если они есть, то выполняется их удаление (метод deleteChildren()). Как видно из исходника объект прекрасно знает о своих потомках и в ходе своего разрушения явно вызывает деструктор для каждого из них.
Итак, а где же виртуальный деструктор?? Конечно, вот же он:
Код:
virtual ~QObject();
Деструктор ~QObject() объявлен виртуальным! А зачем? Пример:
Код:
class Foo: public QObject{
enum{size = 100};
int* m_data;
public:
Foo(QObject* pobj = 0):QObject(pobj){
m_data = new int[size];
}
~Foo(){
delete []m_data;
std::cout << "Foo destructor" << std::endl;
}
};
int main(int argc, char *argv[])
{
QObject* pobj = new Foo;
//do something...
delete pobj;//вызывается деструктор Foo
}
Если бы деструктор ~QObject не был виртуальным, то для указателя pobj был бы вызван деструктор ~QObject, а не ~Foo. Виртуальность позволила выполнить полиморфных вызов нужного деструктора, и, как следствие, выполнить правильную зачистку и избежать утечки памяти. Это и есть назначение виртуальных деструкторов - выполнение корректной зачистки при работе с объектом не напрямую, а через его интерфейс. Как можно видеть, в примере количество new и delete совпадают. Точно так же оно совпадает во внутренней реализации Qt. Сами по себе виртуальные деструкторы никак не помогают избежать явного вызова delete в коде.

Приведенный вами пример, в котором delete для соответствующего new отсутствует, демонстрирует особенность фреймворка. По этому поводу я уже отвечал, что согласен с тем, что учитывать особенности библиотеки нужно обязательно (http://www.prog.org.ru/index.php?topic=11963.msg75112#msg75112 (http://www.prog.org.ru/index.php?topic=11963.msg75112#msg75112)).

Dendy, я ответил на ваш вопрос?


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 07:32
детский сад, честное слово...

ilot, именно вам я давал ссылки по теме. повторю:
1. http://ru.wikipedia.org/wiki/Абстрактная_фабрика_(шаблон_проектирования)
2. http://ru.wikipedia.org/wiki/Строитель_(шаблон_проектирования)
3. http://ru.wikipedia.org/wiki/Одиночка_(шаблон_проектирования)
эти три паттерна, плюс принцип RAII(http://ru.wikipedia.org/wiki/RAII), избавляют программиста от головной боли и утечек памяти.
niXman, я смотрел эти ссылки и даже ответил (http://www.prog.org.ru/index.php?topic=11965.msg75056#msg75056 (http://www.prog.org.ru/index.php?topic=11965.msg75056#msg75056)).
В той же Абстрактной фабрике выполняется явное удаление экземпляров. Посмотрите пример для нее - увидите, что она никак не избавляет программиста от утечек памяти, если он забудет в нужном месте delete вызвать. Более того, в том же примере допущена ошибка, способная в перспективе привести к весьма трудноуловимой утечке памяти.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 07:45
Спасибо за развёрнутое обьяснение что такое виртуальные деструкторы, может кому и пригодится.

Dendy, я ответил на ваш вопрос?

Судя по тому, что продолжаете себе противоречить - нет. И обратите внимание - я не предлагал мне разжёвывать зачем нужны виртуальные деструкторы. Всё что я хотел - чтобы вы обьяснили это себе, можно даже дома перед зеркалом. И да, ваш пример несостоятелен, вы пытаетесь в нём обьяснить зачем нужны виртуальные деструкторы, в то время как пример демонстрирует ровно наоборот.

Ответьте на вопрос: зачем обьявлен:
Код:
QObject* pobj = new Foo;
вместо:
Код:
Foo* pobj = new Foo;
?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 07:53
Забыл процитировать этот момент.

Приведенный вами пример, в котором delete для соответствующего new отсутствует, демонстрирует особенность фреймворка.

Приведённый мною пример ни разу не демонстирирует особенность фреймфорка. Он демонстрирует исключительно возможности C++. Все без исключения классы с виртуальным деструктором предназначены для того, чтобы убрать явный delete из клиентского кода.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 08:20
Судя по тому, что продолжаете себе противоречить - нет.
уму непостижимо где вы видете противоречие ...
И да, ваш пример несостоятелен, вы пытаетесь в нём обьяснить зачем нужны виртуальные деструкторы, в то время как пример демонстрирует ровно наоборот.
именно, пытаюсь объяснить зачем они есть и как используются. А попутно показываю, что сами по себе они не помогают сократить количество записей (как вам угодно) delete коде.
Ответьте на вопрос: зачем обьявлен:
Код:
QObject* pobj = new Foo;
вместо:
Код:
Foo* pobj = new Foo;
?
А зачем вообще нужен полиморфизм? И как он работает? Деструкторы, как обычные функции, могут быть виртуальными, и механизм их вызова точно такой же.
Каждый класс, наследованный от QObject, хранит список указателей на своих потомков:
Код:
typedef QList<QObject*> QObjectList;
Как вы можете видеть указатели имеют тип QObject, и чтобы при удалении потомков корректно вызывались именно их деструкторы (а не деструктор ~QObject()), необходимо реализовать полиморфный вызов. Все, другого назначения у виртуального деструктора нет. Как он помогает сократить количество записей delete в коде знаете, наверное, только вы.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 08:39
Так в вашем примере и нет никакого полиформизма. А вы пытаетесь показать, что он есть и этим оправдать delete pobj. Попытайтесь всё таки обьяснить, зачем в примере экзмепляр обьекта обьявляется в указателе QObject*, а не Foo*.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 09:00
Так в вашем примере и нет никакого полиформизма. А вы пытаетесь показать, что он есть и этим оправдать delete pobj.
Неправда ваша. Я же показал, что деструктор ~QObject() - виртуальный. Это значит, что QObject - Foo образуют полиморфную иерархию. Этот и только этот факт дает нам право удалять объект типа Foo через указатель на QObject. Выше я так и написал
Цитировать
Виртуальность позволила выполнить полиморфный вызов нужного деструктора
Если бы здесь не было полиморфизма (как вы утверждаете), то при выполнении delete pobj вызывался бы деструктор QObject. Не верите мне, можете запустить приведенный пример, и убедиться, что в консоль выводится "Foo destructor".
Попытайтесь всё таки обьяснить, зачем в примере экзмепляр обьекта обьявляется в указателе QObject*, а не Foo*.
Я провожу аналогию с хранением в QObject указателей на свои потомки. Потомками могут быть любые объекты, тип которых наследован от QObject. Хранятся эти указатели в следующем виде:
Каждый класс, наследованный от QObject, хранит список указателей на своих потомков:
Код:
typedef QList<QObject*> QObjectList;
И полиморфизм здесь задействуется для того, чтобы вызывать нужные деструкторы, а не ~QObject() для каждого потомка. В своем предыдущем посте http://www.prog.org.ru/index.php?topic=11963.msg75199#msg75199 (http://www.prog.org.ru/index.php?topic=11963.msg75199#msg75199) я даже специально подчеркнул ключевую фразу.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 09:42
Я же показал, что деструктор ~QObject() - виртуальный.

Так в том то и вопрос - зачем он в вашем примере виртуальный? Что это даёт в вашем примере? Почему деструктор QObject не обычный в вашем примере?

Виртуальность позволила выполнить полиморфный вызов нужного деструктора

Зачем, если в вашем случае указатель на Foo живёт в одной области видимости с его конструктором? Ваш пример наглядно демонстрирует бесполезность какого-либо полиморфизма. И как следствие выводы о необходимости явного delete pobj ложны.

Я провожу аналогию с хранением в QObject указателей на свои потомки.

Примеры не демонстрируют аналогии, а показывают вариант развития событий. Ваш пример не показывает необходимость полиморфизма. Потрудитесь написать пример, в котором полиморфизм таки будет продемонстрирован. Вот тогда и посчитаем количество new/delete в коде.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 10:22
Так в том то и вопрос - зачем он в вашем примере виртуальный? Что это даёт в вашем примере? Почему деструктор QObject не обычный в вашем примере?
Потому что тролли сделали его виртуальным. :D Если вы еще не поняли, то в примере я использовал QObject из библиотеки Qt. ;)

Примеры не демонстрируют аналогии, а показывают вариант развития событий. Ваш пример не показывает необходимость полиморфизма. Потрудитесь написать пример, в котором полиморфизм таки будет продемонстрирован. Вот тогда и посчитаем количество new/delete в коде.
Да я вам уже кусок кода из реализации QObject привел, в котором выполняется зачистка:
Код:
void QObjectPrivate::deleteChildren()
{
    ......
    for (int i = 0; i < children.count(); ++i) {
        currentChildBeingDeleted = children.at(i);
        children[i] = 0;
        delete currentChildBeingDeleted;//вот здесь
    }
    ......
}
Для каждого потомка вызов delete выполняется явно (children.count() раз). currentChildBeingDeleted - имеет тип QObject*. И полиморфизм используется для того, чтобы вызывался не ~QObject(), а деструкторы тех объектов, которые в действительности являются потомками (~QLabel(), ~QLineEdit, ~QPushButton() и т.п.). Пример с Foo я привел для наглядности, как демонстрация применения виртуального деструктора, и что он никак не сокращает количество вызовов delete.

Даже не знаю, что еще добавить. Понимаю, тема сложная - остается только посоветовать доп. литературу... Например, в Thinking in C++, Брюса Эккеля, полиморфизм и применения виртуальных деструкторов неплохо раскрыты.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 10:47
Этот пример как раз и показывает ровно один delete в коде библиотеки на все new производных от QObject'а классов.

Я вижу вы мастер подменять понятия. В третий раз повторю о чём речь:

Речь идёт о количестве записей new/delete в коде, а не о количестве их вызовов во время выполнения.

С чем вы выше по тексту согласились:

> вызовов

Как будто специально не читаете.
переформулирую вопрос:
И как же наличие виртуального деструктора позволит сократить количество записей delete в программе??

После чего вы умело вставляете слова "в коде":

Сами по себе виртуальные деструкторы никак не помогают избежать явного вызова delete в коде.

И последнее ваше перевоплощение, слова "в коде" магическим образом из вашего текста исчезают:

Пример с Foo я привел для наглядности, как демонстрация применения виртуального деструктора, и что он никак не сокращает количество вызовов delete.

Или вы делаете это специально, чтобы запутать других, или действительно не улавливаете суть разговора.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 11:14
Этот пример как раз и показывает ровно один delete в коде библиотеки на все new производных от QObject'а классов.
Очень смешно... Это вообще-то опять заслуга структурной организации: все указатели хранятся в контейнере QList, что делает возможным их перебор в цикле for. Причем здесь концепция виртуальных вызовов - уму непостижимо. Так можно обрабатывать коллекции любых элементов без всякого полиморфизма.

Я вижу вы мастер подменять понятия. В третий раз повторю о чём речь:
Речь идёт о количестве записей new/delete в коде, а не о количестве их вызовов во время выполнения.

С чем вы выше по тексту согласились:
...
После чего вы умело вставляете слова "в коде":

Сами по себе виртуальные деструкторы никак не помогают избежать явного вызова delete в коде.

И последнее ваше перевоплощение, слова "в коде" магическим образом из вашего текста исчезают:

Пример с Foo я привел для наглядности, как демонстрация применения виртуального деструктора, и что он никак не сокращает количество вызовов delete.
Я с этим согласился, и нигде это больше перевирал. Под словами "в коде" я понимал исходный код программы (вызовы в исходном коде, а не во время выполнения). Не знаю, почему вы решили, что я снова имею ввиду вызовы во время выполнения.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 11:42
Вы уж определитесь, нужен для QObject виртуальный деструктор или не нужен. А то вначале вы пишите:

И полиморфизм используется для того, чтобы вызывался не ~QObject(), а деструкторы тех объектов, которые в действительности являются потомками (~QLabel(), ~QLineEdit, ~QPushButton() и т.п.).

А после этого:

Причем здесь концепция виртуальных вызовов - уму непостижимо.

А на счёт этого:

Пример с Foo я привел для наглядности, как демонстрация применения виртуального деструктора, и что он никак не сокращает количество вызовов delete.
Не знаю, почему вы решили, что я снова имею ввиду вызовы во время выполнения.

Во-первых, потому что именно это вы и написали: "никак не сокращает количество вызовов delete". Во-вторых, я вам уже рассказал, что ваш пример демонстрирует ровным счётом ничего. Зачем вам там виртуальный деструктор - вы до сих пор не обьяснили.

Я конечно спрошу ещё раз, хотя думаю вы опять проигнорируете:

Вопрос номер 1: Зачем вам там виртуальный деструктор, если вызов конструктора Foo и его удаление в одной области видимости?
Вопрос номер 2: Почему вы обьявили указатель pobj как QObject*, а не как Foo*?


Название: Re: Основы удаление объектов.
Отправлено: BRE от Январь 09, 2010, 12:04
Бзззз! Ответ неверен.

kibsoft, внимание, отвечает Александр Друзь.

1. На вопрос удаляются ли дочерние виджеты, ответ - да, удаляются.
2. На вопрос почему не вызывается слот crash(), ответ - не потому что соединение было разорвано.
3. На вопрос "а почему тогда?" ответ кроется в недрах C++.

Qt использует виртуальные методы для вызова методов по имени (сигналов и слотов). А как мы знаем из теории - виртуальные методы в деструкторах не работают, поскольку отнаследованный обьект (ваш Widget) был разрушен до базового (QObject). Именно в деструкторе QObject удаляюся дочерние обьекты, сигналы destroyed() от которых уже не могут вызвать виртуальный метод в Widget.
Давайте смотреть....
Разрушение детей QWidget происходит не в деструкторе QObject, а в деструкторе QWidget (Qt 4.6)!
Смотрим код:
Код
C++ (Qt)
QWidget::~QWidget()
{
   ...
   if (!d->children.isEmpty())
       d->deleteChildren();
   ...
}
 
Также, если посмотреть код деструктора QObject, то легко можно видеть, что сначала происходит разрывание всех связей (коннектов) уничтожаемого объекта, а потом уже разрушаются его дети.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 12:13
BRE, да вы правы, очевидно удаление виджетов связано с особенностями оконной системы, поэтому в ~QWidget() они удаляются явно. В любом случае удаление дочерних обьектов происходит уже после того как отработал деструктор собственного класса и разрушилась его таблица виртуальных методов. Даже если бы дочерние обьекты удалялись после разрыва соединений - всё равно сигнал бы не пришёл.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 12:25
Вы уж определитесь, нужен для QObject виртуальный деструктор или не нужен. А то вначале вы пишите:
Фразы, выдранные из контекста..
В первом случае я говорил о том, как используется виртуальность деструктора ~QObject(), и там же (уже не в первый раз) указал, что на количество записей delete в исходном коде программы виртуальность деструктора никак не влияет. И что нужна эта виртуальность только для организации правильной зачистки памяти (пример с Foo это наглядно демонстрирует; собственно для этого я его и делал).
Во втором случае я комментировал вашу фразу:
Этот пример как раз и показывает ровно один delete в коде библиотеки на все new производных от QObject'а классов.
Я аргументировал, что "один delete"  - результат структурной организации (использование списка и перебор данного списка в цикле), а не результат работы виртуального деструктора.
Вы уж определитесь, нужен для QObject виртуальный деструктор или не нужен.
Нужен для правильной зачистки памяти, при этом никакого сокращения количества записей delete он не дает. В моих постах никакой неопределенности по этому вопросу не просматривается.

А вообще диалог зашел в тупик. Я вам уже и оригинальный код из библиотеки Qt приводил, и собственный пример написал, и прокомментировал все - что и зачем. Вы же вместо аргументированных ответов все пытаетесь подловить меня на мнимых противоречиях. Пора бы разбавить темку еще чьим нибудь мнением...


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 12:33
В любом случае удаление дочерних обьектов происходит уже после того как отработал деструктор собственного класса и разрушилась его таблица виртуальных методов.
Удаление дочерних объект происходит во время работы деструктора родителя. Там после
Код:
if (!d->children.isEmpty())
        d->deleteChildren();
еще код есть  ;)

Это значит, что когда уже все потомки удалены, родитель некоторое время продолжает существовать.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 12:39
пример с Foo это наглядно демонстрирует

Пример с Foo не демонстрирует абсолютно ничего. Вы уже в который раз на него ссылаетесь и в который раз я вам это говорю. Почему - обьяснил выше.

Вы же вместо аргументированных ответов...

Ответов на какие вопросы? Не видел ни одного.

А вот мои вопросы, которые я задавал несколько раз так и остались без ответа. Просьба написать пример, где демонстрируется полиморфизм тоже была проигнорирована.

Спрошу в третий раз, интересно, проигнорируете ли вы снова:
Вопрос: Почему вы обьявили указатель pobj как QObject*, а не как Foo*, если вызов конструктора Foo и его удаление в одной области видимости?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 12:54
В любом случае удаление дочерних обьектов происходит уже после того как отработал деструктор собственного класса и разрушилась его таблица виртуальных методов.
Удаление дочерних объект происходит во время работы деструктора родителя.

Присмотритесь что вы комментируете. Деструкторов у обьекта несколько, вызываются они от порождённого класса к базовому. И удаление дочерних обьектов происходит как раз после собственного деструктора. А значит в таблице виртуальных методов обьекта уже будут отсутствовать указатели на переопределённые виртуальные методы (qt_metacall() и другие) собственного класса, потому они и не вызовутся, потому и не вызовутся слоты.


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 09, 2010, 13:57
http://rghost.ru/806868 вот проект..
Все children'ы удаляются автоматычно, все корректно. Да, destroyed в данном случае не приходит потому что, как указал BRE, коннект уже разорван. А разорвать его было необходимо потому что widget уже разрушен (как указал Dendy). Поставьте слот на что-нибудь живущее - и destroyed будет приходить. А убедиться удаляются ли children'ы проще не связываясь с destroyed а напр. так

Код:
class MyLabel : public QLabel {
 public:
  MyLabel( const QString & txt, QWidget * parent = 0 ) : QLabel(txt, parent) {}
 ~MyLabel( void ) { qDebug() << "MyLabel destroyed"; }
};

Edit: перечитав, вижу что Авварон уже ответил - но разве в такой свалке что-то разберешь?  :)


Название: Re: Основы удаление объектов.
Отправлено: Авварон от Январь 09, 2010, 15:36
ненене, там там всё хитрее чем я написал... а тему надо закрыть и отправить спорщиков читать всё с самого начала. Было предложено ТРИ варианта почему не приходят сигналы. А холиварить о словах "явное указание delete в коде" просто бессмысленно


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 16:05
Авварон, а вы, я так понимаю, тот самый Д'Артаньян.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 17:01
Ответов на какие вопросы? Не видел ни одного.
Ответы на мои посты. Их (ваших ответов) предостаточно.
Спрошу в третий раз, интересно, проигнорируете ли вы снова:
Вопрос: Почему вы обьявили указатель pobj как QObject*, а не как Foo*, если вызов конструктора Foo и его удаление в одной области видимости?
Я ни разу не игнорировал ваши вопросы. Отвечал как мог. Отвечу еще раз: только для того, чтобы продемонстрировать работу виртуального деструктора - чтобы удалять экземпляр Foo через указатель типа Foo* виртуальный деструктор не нужен. Чтобы продемонстрировать работу виртуального деструктора именно в том виде, в каком это используется при зачистке списка потомков в деструкторе ~QObject().

Присмотритесь что вы комментируете. Деструкторов у обьекта несколько, вызываются они от порождённого класса к базовому. И удаление дочерних обьектов происходит как раз после собственного деструктора. А значит в таблице виртуальных методов обьекта уже будут отсутствовать указатели на переопределённые виртуальные методы (qt_metacall() и другие) собственного класса, потому они и не вызовутся, потому и не вызовутся слоты.
Dendy, вы все правильно говорите, но вы меня не поняли... :( Разбор объекта действительно происходит начиная с деструктора порожденного класса и, двигаясь вверх по иерархии наследования, заканчивается вызовом деструктора базового класса. Все как вы говорите.. но дело в том, что отношение "родитель-потомок" в контексте библиотеки Qt это не тоже самое, что отношение "базовый класс - производный класс" в контексте наследования. В Qt объект ("родитель") хранит список указателей на зависящие от него объекты (для них применяется термин "дочерние"). С точки зрения стандарта С++ такое отношение называется композицией. Перед тем как объект перестанет существовать, он обязан удалить все данные за которые он отвечает. Если он не удалить все эти объекты, указатели на которые он хранит ("дочерние"), до завершения своего деструктора, то их уже не удалит никто, поскольку этих указателей больше не будет (а сами "дочерние" объекты останутся в памяти).

А холиварить о словах "явное указание delete в коде" просто бессмысленно
Согласен. Я, честно говоря, думал, что Dendy просто случайно сослался на концепцию полиморфизма, как средство, позволяющее не заботится о вызовах delete. Оказалось нет. А тема эта довольно важная (как в чистом C++, так и в контексте библиотеки Qt), поэтому странно, что никто больше не высказался (может быть тогда и пришли к какому-то заключению).

P.S. трудно наполнить чашу, которая уже полна.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 17:38
Попробую отрезюмировать. На основании стандарта C++ и собственного опыта разработки я могу заключить следующее: количество new/delete в коде никак друг с другом не соотносятся. Вот пример с несколькими delete и одним new:

Код
C++ (Qt)
typedef int A;
 
class B
{
public:
   A * create( int index )
   {
       return values_[ index ] = new A;
   }
 
   void destroy( int index )
   {
       delete values_.take( index );
   }
 
   void clear()
   {
       foreach ( A * value, values_ )
           delete value;
       values_.clear();
   }
 
private:
   QHash<int,A*> values_;
};
 

Посчитайте new и delete. Это живой пример, их количество никак не соотносится. Вариантов конструирования и уничтожения может быть множество.

За счёт виртуальных деструкторов и шаблонов уничтожение обьектов можно полностью локализировать в библиотечные функции, снизив их количество в клиентском коде до нуля. Попробуйте написать пример класса с виртуальным деструктором, количество new/delete в коде для которого будет один к одному. Такое просто невозможно. Хотя для интереса таки стоит, очень способствует саморазвитию.

Возьмите другие языки - Java/C#, там вообще отсутствует явное управление памятью, на высоком уровне вам дают оперировать разве что счётчиками ссылок. Соотношение явных аллокаций к уничтожениям - N/0. Возьмите Objective-C, там весь рантайм построен на основе retain/release, тем не менее абсолютное большинство обьектов после аллокации помещаются в autorelease pool, а некоторым сразу же вызывается autorelease, чтобы случайно не забыть про деаллокацию где-то там в конце функции. Явное удаление способствует ошибкам при работе с памятью - где-то забыли удалить, получили утечку, где-то удалили два раза, получили креш. Каждый язык/фреймворк предоставляет свои механизмы для деаллокации данных. Писать на каждый new свой delete в C++ - глупость.


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 09, 2010, 17:57
Цитировать
За счёт виртуальных деструкторов и шаблонов уничтожение обьектов можно полностью локализировать в библиотечные функции, снизив их количество в клиентском коде до нуля.
я об этом уже два дня твержу! и как горох об стену!


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 09, 2010, 18:04
Попробую отрезюмировать. На основании стандарта C++ и собственного опыта разработки я могу заключить следующее: количество new/delete в коде никак друг с другом не соотносятся. Вот пример с несколькими delete и одним new:
Реализация как в примере - конечно плохо. Но никто не мешает сделать QList для хранения A и освободить class B от всех забот по созданию/удалению экземпляров A (эта ф-циональность класса B совершенно неестественна). Я согласен с Вами что 2 и более delete (для того же объекта) = верная примета что спроектировано плохо. Но считать число delete как "показатель качества программы" - это уж чересчур, мне кажется тут Вы перегибаете палку.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 18:10
Попробуйте написать пример класса с виртуальным деструктором, количество new/delete в коде для которого будет один к одному. Такое просто невозможно. Хотя для интереса таки стоит, очень способствует саморазвитию.
Вполне рабочий код:
Код:
class Foo{
enum{size = 100};
int* m_data;
public:
Foo(){
m_data = new int[size];
}
virtual ~Foo(){
delete []m_data;
}
};

Dendy, в целом вы все говорите правильно, но дальше уже пошла игра слов :D Мне вспомнилась притча про трех слепых старцев, которые пытались на ощупь описать характеристики слона. Первый взялся за хобот и сказал: "Слон - это нечто длинное и гибкое, как змея..". Второй взялся за ногу и сказал: "Слон - это нечто похожее на ствол крепкого дерева, растущего из земли...". Третий взялся за ухо... (что он сказал можете придумать сами). Так и мы с вами отстаиваем каждый своего "слона". :D
Я уже не вижу способов разрешить недопонимание на страницах данного форума; дальше уже надо беседовать за бутылочкой хорошего коньяка, с наглядным материалом под рукой ;D Так что давайте заканчивать этот флуд...

P.S. Я не сколько не сомневаюсь в вашей компетентности, и мне очень приятно было с вами побеседовать.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 18:16
я об этом уже два дня твержу! и как горох об стену!
ваше "твержу", niXman, я видел неоднократно, так же неоднократно отвечал, например вот http://www.prog.org.ru/index.php?topic=11963.msg75200#msg75200 (http://www.prog.org.ru/index.php?topic=11963.msg75200#msg75200)


Название: Re: Основы удаление объектов.
Отправлено: niXman от Январь 09, 2010, 18:48
вы читать-то до конца не пробовали? пофантазировать? похоже что нет. потому, именно для вас, я разжевал: http://www.prog.org.ru/index.php?topic=11963.msg75150#msg75150
и все равно горох...


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 19:16
Я согласен с Вами что 2 и более delete (для того же объекта) = верная примета что спроектировано плохо.

Погодите, я не говорил, что это плохо. В библиотечном классе, который я привёл в пример - это абсолютно нормально, реализовать столько вариантов деаллокаций сколько нужно. Главное что они не торчат наружу. Мой пример был как противовес утверждению "на каждый new сразу пишем delete". Как видим, количество new/delete не соотносятся один к одному.

Но считать число delete как "показатель качества программы" - это уж чересчур, мне кажется тут Вы перегибаете палку.

Отнюдь. Покажите мне delete в клиентском коде и я покажу как его можно было бы избежать, тем самым повысив безопастность работы с памятью.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 19:17
Вполне рабочий код:
Код:
class Foo{
enum{size = 100};
int* m_data;
public:
Foo(){
m_data = new int[size];
}
virtual ~Foo(){
delete []m_data;
}
};

Вообще речь шла про выделение/уничтожение наследников класса Foo.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 09, 2010, 19:33
Вообще речь шла про выделение/уничтожение наследников класса Foo.
Пожалуйста:
Код:
class Foo{
enum{size = 100};
int* m_data;
public:
Foo(){
m_data = new int[size];
}
virtual ~Foo(){
delete []m_data;
std::cout<< "Foo destructor" << std::endl;
}
};
class Derived1: public Foo{
int x;
public:
Derived1():Foo(),x(0){}
virtual ~Derived1(){
std::cout << "Derived1 destructor" << std::endl;
}
};
class Derived2: public Foo{
int* m_d;
public:
Derived2():Foo(),m_d(0){
m_d = new int(1);
}
virtual ~Derived2(){
delete m_d;
std::cout << "Derived2 destructor" << std::endl;
}
};
int main(int argc, char *argv[])
{
Derived1 *pd1 = new Derived1;
Derived2 *pd2 = new Derived2;
//do something...
delete pd1;
delete pd2;
}
У обоих наследников количестов new и delete совпадает.


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 09, 2010, 19:39
Погодите, я не говорил, что это плохо. В библиотечном классе, который я привёл в пример - это абсолютно нормально, реализовать столько вариантов деаллокаций сколько нужно. Главное что они не торчат наружу.
Не хватало еще чтобы они торчали наружу. Вы задумали
Код:
QHash<int,A*> values_;
Понятно, хотите быстро работать с указателями, а не месить сами объекты (напр. при каждой сортировке). Но с какой стати такая конструкция выделяет/удаляет экземпляры A? Это было бы уместно для  QHash<int,A>. но никак не для QHash<int,A*>. Поручите это QList<A>, он может быть напр. членом того же класса B. Так что говорили Вы или нет - все равно это плохо  :)


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 20:39
Пожалуйста:
Код:
class Foo{
enum{size = 100};
int* m_data;
public:
Foo(){
m_data = new int[size];
}
virtual ~Foo(){
delete []m_data;
std::cout<< "Foo destructor" << std::endl;
}
};
class Derived1: public Foo{
int x;
public:
Derived1():Foo(),x(0){}
virtual ~Derived1(){
std::cout << "Derived1 destructor" << std::endl;
}
};
class Derived2: public Foo{
int* m_d;
public:
Derived2():Foo(),m_d(0){
m_d = new int(1);
}
virtual ~Derived2(){
delete m_d;
std::cout << "Derived2 destructor" << std::endl;
}
};
int main(int argc, char *argv[])
{
Derived1 *pd1 = new Derived1;
Derived2 *pd2 = new Derived2;
//do something...
delete pd1;
delete pd2;
}
У обоих наследников количестов new и delete совпадает.

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


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 09, 2010, 20:45
Igors, я мало что понял из того что вы написали. Внутренности вас волновать не должны. A - мой собственный класс, что хочу в нём - то и храню. Вы не можете навязывать хранение по значению, так как класс может быть не перемещаем. Всё что показывает пример - несоответствие количества new количеству delete.


Название: Re: Основы удаление объектов.
Отправлено: Igors от Январь 09, 2010, 21:33
Igors, я мало что понял из того что вы написали. Внутренности вас волновать не должны. A - мой собственный класс, что хочу в нём - то и храню. Вы не можете навязывать хранение по значению, так как класс может быть не перемещаем. Всё что показывает пример - несоответствие количества new количеству delete.
Я хотел просто сказать - спланируйте класс удачнее и "количество написанных delete" (правильно  :)?) схлопнется само сабой


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 05:45
Отделил последнее сообщение в новую тему: http://www.prog.org.ru/topic_11985_0.html


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 10, 2010, 07:22
А теперь подумайте и скажите, зачем вам здесь вообще виртуальный деструктор, если вы обьекты удаляете явно?
1. Во-первых это ответ на ваше утверждение:
Попробуйте написать пример класса с виртуальным деструктором, количество new/delete в коде для которого будет один к одному. Такое просто невозможно. Хотя для интереса таки стоит, очень способствует саморазвитию.

2. А вы таки думаете, что при выходе из области видимости переменных pd1 и pd2 объекты, на которые они указывают, удалятся сами??


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 07:27
ilot, ещё раз перечитайте мой вопрос. Я уже не знаю как проще обьяснить. Ваш пример совершенно не демонстрирует возможности виртуального деструктора. Если заменить его на невиртуальный - результат будет тот же.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 10, 2010, 07:43
Ваш пример совершенно не демонстрирует возможности виртуального деструктора. Если заменить его на невиртуальный - результат будет тот же.
Абсолютно точно! Я и не говорил, что этот пример должен демонстрировать работу виртуального деструктора. Я привел примеры классов с виртуальным деструктором, количество new/delete в которых совпадает, и возможность существования которых вы отрицали.
А вот мой самый первый пример с Foo (к которому у вас большие претензии) как раз наглядно демонстрирует работу виртуального деструктора.

Я уже не знаю как проще обьяснить. Ваш пример совершенно не демонстрирует возможности виртуального деструктора.
Напишите свой пример, демонстрирующий его возможности ;)


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 09:02
Я и не говорил, что этот пример должен демонстрировать работу виртуального деструктора.

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


Название: Re: Основы удаление объектов.
Отправлено: lit-uriy от Январь 10, 2010, 09:49
Dendy, пиши ТЗ на пример, чёткое не двусмысленное. Чтобы в одном сообщение было только оно и ничего больше, ни каких обсуждений.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 10:25
Написать пример, в котором:

а) демонстрируется использование виртуального деструктора в классе;
б) количество new/delete в коде для этого класса (или его наследников) совпадало.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 11:44
Написать пример, в котором:

а) демонстрируется использование виртуального деструктора в классе;
б) количество new/delete в коде для этого класса (или его наследников) совпадало.
Вам уже писали такой пример:

class Foo: public QObject{
   enum{size = 100};
   int* m_data;
public:
   Foo(QObject* pobj = 0):QObject(pobj){
      m_data = new int[size];
   }
   ~Foo(){
      delete []m_data;
      std::cout << "Foo destructor" << std::endl;
   }
};
int main(int argc, char *argv[])
{
   QObject* pobj = new Foo;
   //do something...
   delete pobj;//вызывается деструктор Foo
}


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 11:53
BigZ, прочитайте весь тред. Выше я уже указал, что пример не демонстрирует смыл виртуального деструктора, поскольку нет ни одной причины хранить указать на экземпляр Foo в QObject*, а не в Foo*. Вопрос не в теории как оно работает, а в реальной задаче, которую виртуальный деструктор призван выполнять.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 12:00
Да, я прочитал конечно. Пример отлично демонстрирует возможности виртуального деструктора. Как считаешь ~Foo() в данном примере виртуальный или нет?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 12:19
Когда я сказал:
пример не демонстрирует смыл виртуального деструктора
то указал почему:
поскольку нет ни одной причины хранить указать на экземпляр Foo в QObject*, а не в Foo*

Ваши же слова лишены аргументов:
Пример отлично демонстрирует возможности виртуального деструктора.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 12:28
поскольку нет ни одной причины хранить указать на экземпляр Foo в QObject*, а не в Foo*
Причина есть и существенная, продемонстрировать возможности виртуального деструктора.

Ваши же слова лишены аргументов:
>>Пример отлично демонстрирует возможности виртуального деструктора.
Чтобы эти слова стали аргументом нужен ответ на мой вопрос - ~Foo() в данном примере виртуальный или нет и почему?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 12:45
Причина есть и существенная, продемонстрировать возможности виртуального деструктора.

- Грузины лучше, чем армяне.
- Чем?
- Чем армяне.

Демонстрация возможности призвана показать, как данный приём позволяет решить задачу, которую невозможно решить другим способом. В даном случае смысл в виртуальном деструктора отсутствует, поскольку если его убрать - задача решается точно так же, заменой QObject* на Foo*. Попробуйте обьяснить новичку зачем Страуструп придумал виртуальные деструкторы, когда задача выполняется простой заменой QObject* на Foo*. Этот пример не показывает ничего, придумайте другой.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 12:52
class Foo: public QObject{
   enum{size = 100};
   int* m_data;
public:
   Foo(QObject* pobj = 0):QObject(pobj){
      m_data = new int[size];
   }
   ~Foo(){
      delete []m_data;
      std::cout << "Foo destructor" << std::endl;
   }
};

void deleteQObject(QObject* pobj)
{
   delete pobj;//вызывается деструктор Foo
}

int main(int argc, char *argv[])
{
   Foo* pobj = new Foo;
   //do something...
   deleteQObject(pobj);
}

Хм... так понятнее?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 12:59
Новичёк задаёт резонный вопрос: почему deleteQObject принимает указатель на QObject, а не на Foo? И ещё он спраишвает, зачем вообще нужен метод deleteQObject, если то же самое можно сделать, вызвав просто delete?

Очевидно, вы так и не поняли. Я не прошу любой код с виртуальным деструктором. Я прошу показать задачу, которую он призван выполнять. Задачу, которую иначе решить нельзя. Задачу, в которой виртуальный деструктор необходим.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 13:07
class Foo: public QObject{
public:
   Foo(QObject* pobj = 0) {}
   ~Foo(){}
};

class Foo2: public QObject{
public:
   Foo2(QObject* pobj = 0) {}
   ~Foo2(){}
};

void deleteQObject(QObject* pobj)
{
#ifdef DEBUG
   static int destroyCallsCount = 0;
   destroyCallsCount++;
#endif
   delete pobj;//вызывается деструктор объекта наследованного от QObject
}

int main(int argc, char *argv[])
{
   Foo* pobj = new Foo;
   Foo2* pobj2 = new Foo2;

   //do something...
   deleteQObject(pobj);
   deleteQObject(pobj2);
}

Теперь понятно какую задачу решает deleteQObject, почему он принимает в качестве параметра QObject а не Foo, и где в этом примере используется виртуальный деструктор?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:10
Отличный пример, спасибо. То что я ожидал увидеть. Как видим - 2 new, 1 delete, что и требовалось доказать.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 10, 2010, 13:15
Демонстрация возможности призвана показать, как данный приём позволяет решить задачу, которую невозможно решить другим способом.
Слишком сильное утверждение. Практически всегда для задачи существует несколько решений, каждое из которых представляет собой лишь одну из возможностей.

Написать пример, в котором:

а) демонстрируется использование виртуального деструктора в классе;
б) количество new/delete в коде для этого класса (или его наследников) совпадало.
В демонстрационных целях разрабатывается простой контейнер Stack.

Проблема состоит в следующем: нужно чтобы в контейнере Stack можно было хранить объекты разных типов, но при этом не использовать указатели на void. Одно из возможных решений - шаблоны. С целью демонстрации работы виртуального деструктора реализуется подход, основанный на полиморфизме. В рассматриваемом далее решении используется так называемая однокоренная иерархия. Чтобы решить проблему типизации объектов, мы создаем чрезвычайно простой базовый класс Object, содержащий виртуальный деструктор. Далее в контейнере Stack сохраняются указатели на объекты классов, производных от Object, демонстрируется работа с ними через общий интерфейс. В приводимом примере корректная зачистка памяти возможна только при наличии виртуального деструктора.

Господа, можете начинать подсчитывать количество new/delete в исходном коде, сама возможность существования которого опровергалась. :)

Код:
//Stack.h
#ifndef STACK_H
#define STACK_H

#include "ObjectsHierarchy.h"

class Stack{
struct Node{
Object* data;
Node* next;
Node(Object* _data, Node* _next): data(_data), next(_next){}
}* top;
public:
Stack():top(0){}
~Stack(){
//контейнер Stack не является владельцем объектов типа Object - за их создание и удаление
//отвечает код, использующий экземпляр класса Stack. Удаляются только узлы Node
while(top) pop();
}
void push(Object* _data){
top = new Node(_data, top);
}
Object* peek() const{
return (top ? top->data : 0);
}
Object* pop(){
if(top == 0) return 0;
Object* result = top->data;
Node* oldTop = top;
top = top->next;
delete oldTop;
return result;
}
};

#endif //STACK_H

//ObjectsHierarchy.h
#ifndef OBJECT_HIERARCHY_H
#define OBJECT_HIERARCHY_H

#include <iostream>

typedef unsigned char byte;
typedef unsigned int uint;
const unsigned int default_size = 100;

class Object{
public:
Object(){}
virtual ~Object(){
std::cout<< "Object destructor" << std::endl;
}
virtual char* presentation() = 0;
};

class Derived1: public Object{
byte *m_data;
public:
Derived1(uint size = default_size): Object(){
m_data = new byte[size];
}
virtual ~Derived1(){
delete []m_data;
std::cout << "Derived1 destructor" << std::endl;
}
char* presentation(){return "I'm class Derived1";}
static Derived1* create(uint size = default_size){
return new Derived1(size);
}
void remove(){
delete this;
}
};

class Derived2: public Object{
byte *m_data;
public:
Derived2(uint size = default_size): Object(){
m_data = new byte[size];
}
virtual ~Derived2(){
delete []m_data;
std::cout << "Derived2 destructor" << std::endl;
}
char* presentation(){return "I'm class Derived2";}
static Derived2* create(uint size = default_size){
return new Derived2(size);
}
void remove(){
delete this;
}
};
#endif //OBJECT_HIERARCHY_H

//main.cpp

#include <iostream>
#include "Stack.h"
#include "ObjectsHierarchy.h"

int main(){
Stack st;
//заполняем контейнер разнородными объектами
for(uint i = 0; i < 5; i++){
st.push(Derived1::create(i*10));
}
for(uint i = 5; i < 10; i++){
st.push(Derived2::create(i*10));
}
st.push(new Derived1(1000));//до кучи
Object* p = 0;
while(p = st.pop()){
//унифицированно работаем с объектами через их общий интерфейс
std::cout << p->presentation() << std::endl;
//удаляем больше не нужные объекты
delete p;//работает виртуальный деструктор
}

return 0;
}


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:30
Один delete в main() на все два new - для Derived1 и Derived2. Что и требовалось доказать.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 13:31
Отличный пример, спасибо. То что я ожидал увидеть. Как видим - 2 new, 1 delete, что и требовалось доказать.
class Foo: public QObject{
public:
   Foo(QObject* pobj = 0) {}
   ~Foo(){}
};

class Foo2: public QObject{
public:
   Foo2(QObject* pobj = 0) {}
   ~Foo2(){}
};

int main(int argc, char *argv[])
{
   QObject* pobj = new Foo;
   QObject* pobj2 = new Foo2;
   QObject* temp;
   temp = pobj;
   pobj = pobj2;
   pobj2 = temp;
   //do something...
   delete pobj;
   delete pobj2;
}

Функция deleteQObject была нужна чтобы показать, что пример с Foo()
"Демонстрирует возможности виртуального деструктора".
Я рад, что вы наконец с этим согласились и приняли этот пример.
Новый пример показывает реальную возможность обмена между двумя
переменными одного типа. Как видим тут используется два new и два delete.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 10, 2010, 13:34
Один delete в main() на все два new - для Derived1 и Derived2. Что и требовалось доказать.
где вы видите два new в main?? :o

Напоминаю вам ваши же слова: "речь идет о количестве записей new/delete в коде"


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:40
Изначально вопрос стоял как: отношение количества new на количество delete не одно у одному. Отношение N к M, где N и M - независящие друг от друга числа. Если в вашем примере сделать grep new и grep delete и их количество совпадёт, то разве что случайно. Присмотревшись мы именно это и видим.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:40
ilot, мы с вами не в суде.


Название: Re: Основы удаление объектов.
Отправлено: ритт от Январь 10, 2010, 13:42
9 страниц ни о чём. мб пора уже закрыть тему?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:44
BigZ, всё хорошо, только маленькое "но". Если убрать виртуальный деструктор и заменить QObject*pobj и QObject*pobj2 на Foo*pobj и Foo2*pobj2, то (пабам!) код остаётся таким же рабочим и снова неясен смысл виртуальных деструкторов.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:46
Константин, пожалуйста без офтопа.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 13:49
BigZ, всё хорошо, только маленькое "но". Если убрать виртуальный деструктор и заменить QObject*pobj и QObject*pobj2 на Foo*pobj и Foo2*pobj2, то (пабам!) код остаётся таким же рабочим и снова неясен смысл виртуальных деструкторов.
Не согласен. Если сделать так, то программа не скомпилируется. Не возможно в ссылке Foo2 хранить ссылку на Foo.


Название: Re: Основы удаление объектов.
Отправлено: ilot от Январь 10, 2010, 13:50
есть ТЗ:
Написать пример, в котором:

а) демонстрируется использование виртуального деструктора в классе;
б) количество new/delete в коде для этого класса (или его наследников) совпадало.
есть реализованный пример. Остальное демагогия.
9 страниц ни о чём. мб пора уже закрыть тему?
согласен, говорить давно уже не о чем

P.S. разве что голосование провести


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:54
BigZ, всё хорошо, только маленькое "но". Если убрать виртуальный деструктор и заменить QObject*pobj и QObject*pobj2 на Foo*pobj и Foo2*pobj2, то (пабам!) код остаётся таким же рабочим и снова неясен смысл виртуальных деструкторов.

Хотя, нет, облажался, не совсем так. Имелось в виду конечно же, если указатели не меняются в процессе работы. Другими словами, новичёк задаёт вопрос:

А зачем менять указатели друг на друга, если можно просто создать две другие переменные:

Код
C++ (Qt)
int main(int argc, char *argv[])
{
  Foo* pobj = new Foo;
  Foo2* pobj2 = new Foo2;
 
  QObject* pobjCopy = something ? pobj : pobj2;
  QObject* pobj2Copy = something ? pobj2 : pobj;
  //do something...
 
  delete pobj;
  delete pobj2;
}
 

И задача будет точно так же выполняться.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 13:57
ilot, под одинаковым количество имелось в виду соответствие на каждый new свой delete.


Название: Re: Основы удаление объектов.
Отправлено: BigZ от Январь 10, 2010, 14:08
Хотя, нет, облажался, не совсем так. Имелось в виду конечно же, если указатели не меняются в процессе работы. Другими словами, новичёк задаёт вопрос:

А зачем менять указатели друг на друга, если можно просто создать две другие переменные:

Код
C++ (Qt)
int main(int argc, char *argv[])
{
  Foo* pobj = new Foo;
  Foo2* pobj2 = new Foo2;
 
  QObject* pobjCopy = something ? pobj : pobj2;
  QObject* pobj2Copy = something ? pobj2 : pobj;
  //do something...
 
  delete pobj;
  delete pobj2;
}
 
Опять не согласен. Во первых ваш пример всё ещё не компилируется, так как не ясно,
что такое "something". Во вторых вы мой пример отрефакторили не оптимально и сделали его хуже.
У меня используется только одна временная переменная temp а у вас две pobjCopy и pobj2Copy.
Плюс мою переменную можно использовать дальше для других целей, а у вас эти
переменные всегда заняты. В третьих ваша пример будет работать не так как мой. Так как у меня
вызывается вначале деструктор Foo2 а потом Foo.

И ещё четвёртое. В вашем примере всё равно 2 оператора new и 2 оператора delete. Что и требовалось доказать.


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 10, 2010, 14:53
BigZ, код - не самоцель. Цель - задача, которую код призван выполнять.

не ясно, что такое "something"
Это неважно.

Во вторых вы мой пример отрефакторили не оптимально и сделали его хуже.
Отличный аргумент! Но у меня есть контраргумент - я сделал его лучше.

У меня используется только одна временная переменная temp а у вас две pobjCopy и pobj2Copy. Плюс мою переменную можно использовать дальше для других целей, а у вас эти переменные всегда заняты.
Это не есть цель задачи.

В третьих ваша пример будет работать не так как мой. Так как у меня вызывается вначале деструктор Foo2 а потом Foo.
Это единственное, что имеет смысл - виртуальными деструкторами можно выбирать порядок их вызова. Хотя в реальной задаче применение этому вижу с трудом.

И ещё четвёртое. В вашем примере всё равно 2 оператора new и 2 оператора delete. Что и требовалось доказать.
Не спешите. В моём коде отсутствуют виртуальные деструкторы.


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 13, 2010, 23:26
А вот такой вопрос: есть указатели, которые не были созданы с помощью new, а просто приняли адрес объекта - что с ними делать? delete не нужен же?
Например: Object *a2=a1;


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 13, 2010, 23:32
Естественно. Я даже обобщу: delete не нужен (-:


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 13, 2010, 23:50
А как они удаляются тогда?


Название: Re: Основы удаление объектов.
Отправлено: Dendy от Январь 13, 2010, 23:55
Наследники QObject как правило создаются дочерними от другого QObject'а, который в свою очередь является дочерним другого и так далее. А самый верхний как правило хранится по значению и удаляется при выходе из области видимости или при разрушении структуры. Есть ещё обьекты, часто использующиеся по значению без аллокации и наследования, например QFile, QSettings.


Название: Re: Основы удаление объектов.
Отправлено: kibsoft от Январь 13, 2010, 23:57
Понятно, спасибо Dendy :)


Название: Re: Основы удаление объектов.
Отправлено: SASA от Январь 14, 2010, 11:01
А вот такой вопрос: есть указатели, которые не были созданы с помощью new, а просто приняли адрес объекта - что с ними делать? delete не нужен же?
Например: Object *a2=a1;
Я вижу сторублёвую бумажку. Вопрос брать или не брать?
P.S. бумажку можно увидеть у себя в заначке, на дороге, в кассе супермаркета, в кошельке соседа...


Название: Re: Основы удаления объектов
Отправлено: lenny от Февраль 18, 2011, 23:52
UP
Ну вы тут бодягу развели на пустом месте. У меня вопрос появился по теме.
Код:
//EditWindow производный от QGraphicsView в нем scene

void EditWindow::dropEvent(QDropEvent *event)
{
    QComboBox *X = new QComboBox();                //Здесь я не пойму кокого parent-ом указать
    d->addItem("0");
    d->addItem("1");
    QGraphicsProxyWidget *proxy = scene->addWidget(d);  //Судьба *X мне известна, автоматом 
    proxy->setPos(event->pos().x(), event->pos().y());  //он не удалится
}
Можно конечно обойти эту ситуацию, например: складывать X в список а потом их удалить явным образом, но интересно, что можно указать parent-ом для X?


Название: Re: Основы удаления объектов
Отправлено: lenny от Февраль 24, 2011, 10:48
Вопрос снят.