Re[4]: А когда может не вызываться деструктор?
От: jazzer Россия Skype: enerjazzer
Дата: 25.01.13 14:03
Оценка: +1
Здравствуйте, rg45, Вы писали:

A>>

A>>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
A>>Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.


A>>это же чушь.


R>Это высказывание является прямым следствием из 5.3.5/3.


struct A { virtual f(); ~A(); };
struct B:A { f(); };

int main()
{
  B b;
  A* pa = &b;
  pa->f(); //полиморфный!
}

Здесь В замечательно обходится без виртуального деструктора и все корректно уничтожается, а 5.3.5/3 идет по градиенту.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: А когда может не вызываться деструктор?
От: Evgeny.Panasyuk Россия  
Дата: 25.01.13 14:10
Оценка: +1
А>>Какие могут быть ситуации, когда не вызывается дестуктор(сделал new и не сделал delete не в счет)?

V>Классический пример — отсутствие виртуального деструктора — http://cpp-reference.ru/articles/virtual-destructor/


В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.

Технически никому он ничего не должен, особенно если:
1. он protected
2. delete вызывается не на Base*, хотя хранится именно Base* (например deleter в shared_ptr знающий правильный тип, хотя хранится Base*)
3. как показано выше — объект может быть локальным

Но, ссылка выше это же rule of thumb для новичков?
Re[5]: А когда может не вызываться деструктор?
От: sts  
Дата: 25.01.13 14:13
Оценка:
Здравствуйте, jazzer, Вы писали:

J>int main()

J>{
J> B b;
J> A* pa = &b;
pa->>f(); //полиморфный!
J>}
J>[/ccode]
J>Здесь В замечательно обходится без виртуального деструктора и все корректно уничтожается, а 5.3.5/3 идет по градиенту.

разрушение объекта производного класса через указатель на соответствующий базовый класс

тут нет уничтожения через указатель на базовый
Re[3]: А когда может не вызываться деструктор?
От: sts  
Дата: 25.01.13 14:19
Оценка: +1 -1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

А>>>Какие могут быть ситуации, когда не вызывается дестуктор(сделал new и не сделал delete не в счет)?


V>>Классический пример — отсутствие виртуального деструктора — http://cpp-reference.ru/articles/virtual-destructor/


EP>

EP>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
EP>Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.

EP>Технически никому он ничего не должен, особенно если:
EP>1. он protected
тогда не получится "удалять через указатель на базовый класс"
EP>2. delete вызывается не на Base*, хотя хранится именно Base* (например deleter в shared_ptr знающий правильный тип, хотя хранится Base*)
там нет "удаления через указатель на базовый класс" — сначала указателю делается статик-каст к фактическому типу
EP>3. как показано выше — объект может быть локальным
там тоже нет "удаления через указатель на базовый класс"

EP>Но, ссылка выше это же rule of thumb для новичков?

это да
но и пятница же
Re[4]: А когда может не вызываться деструктор?
От: Evgeny.Panasyuk Россия  
Дата: 25.01.13 14:26
Оценка: +2 :))
Здравствуйте, sts, Вы писали:

sts>тогда не получится "удалять через указатель на базовый класс"


sts>там нет "удаления через указатель на базовый класс" — сначала указателю делается статик-каст к фактическому типу


sts>там тоже нет "удаления через указатель на базовый класс"


это же ответ на:

В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.

которое стоит самым первым предложением.

По аналогии можно сказать:

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



EP>>Но, ссылка выше это же rule of thumb для новичков?

sts>это да
sts>но и пятница же

Re: А когда может не вызываться деструктор?
От: sts  
Дата: 25.01.13 14:27
Оценка: -1
Здравствуйте, Аноним, Вы писали:

А>Помогите новичку!

А>Какие могут быть ситуации, когда не вызывается дестуктор(сделал new и не сделал delete не в счет)?

Ну еще на такое можно нарваться:
// .h

struct Owner
{
  Owner();
  // ~Owner();
  std::auto_ptr<class Impl> pImpl;
};


// .cpp

#include "Impl.h"

Owner::Owner()
  : pImpl(new Impl())
{}

//Owner::~Owner()
//{}


Удаление неполного класса — одни из самых неприятных плюсовых граблей.
Тоже деструктор pImpl не будет вызван.
Лечится через unique_ptr (который не даст удалить неполный тип) и добавление ~Owner() туда, где Impl уже определен.
Re[5]: А когда может не вызываться деструктор?
От: sts  
Дата: 25.01.13 14:32
Оценка: -1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>

EP>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.

EP>которое стоит самым первым предложением.

EP>По аналогии можно сказать:

EP>

EP>На планете Земля, все люди должны носить шлем. Только так обеспечивается защита головы при падениях с мотоцикла.


я понял кто за что борется
ну да, не должен
но корректное удаление через указатель на объект базового класса только так
Re[5]: А когда может не вызываться деструктор?
От: rg45 СССР  
Дата: 25.01.13 14:42
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, rg45, Вы писали:


A>>>

A>>>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
A>>>Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.


A>>>это же чушь.


R>>Это высказывание является прямым следствием из 5.3.5/3.


J>
J>struct A { virtual f(); ~A(); };
J>struct B:A { f(); };

J>int main()
J>{
J>  B b;
J>  A* pa = &b;
  pa->>f(); //полиморфный!
J>}
J>

J>Здесь В замечательно обходится без виртуального деструктора и все корректно уничтожается, а 5.3.5/3 идет по градиенту.

Где в этом примере (цитирую) "разрушение объекта производного класса через указатель на соответствующий базовый класс" о котором шла речь выше?

Да, к сожалению, авторы статьи не дали четкого определения, что они понимают под полиморфным классом. Из общего контекста статьи можно догадаться, что они вкладывали в это понятие более широкий смысл — класс, объекты которого могут не только использоваться, но и удаляться через указатель базового класса (именно этому вопросу в статье уделено много внимания). Конечно же, это недочет, неточность формулировки, но еще не повод разбрасываться ярлыками типа "чушь" и "говносайт".
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: А когда может не вызываться деструктор?
От: Abyx Россия  
Дата: 25.01.13 15:09
Оценка:
Здравствуйте, vitcpp, Вы писали:

V>>>Почему чушь? Обоснуйте.

A>>http://rsdn.ru/forum/cpp/5044673.1
Автор: Abyx
Дата: 25.01.13


V>Это все понятно. Полагаю, вы слишком формально подходите к статье, и вас смутило слово 'должен'. Но по сути, описано хорошее правило делать деструктор виртуальным в случае полиморфных типов. Можно использовать обычный деструктор, если вы точно уверены, как именно ваша иерархия классов будет использоваться или в целях оптимизации.


хорошее правило — это 'не делать того что не нужно делать' или 'делать только то что нужно делать'.
если виртуальный деструктор не нужен, то незачем его делать.
In Zen We Trust
Re[5]: А когда может не вызываться деструктор?
От: rg45 СССР  
Дата: 25.01.13 15:10
Оценка: +1
Здравствуйте, Abyx, Вы писали:

A>это не может быть следствием, т.к. `delete pointer-to-base-type;` это не единственный способ корректно разрушить объект через указатель на его базовый класс.


Вероятно, ты имеешь ввиду технику, подобную той, которая применяется в shared_ptr? Ну так в ней разрушение объекта производится как раз через указатель most derived класса (при правильно использовании, при неправильном можно получить все то же UB). При этом сам shared_ptr я бы рассматривал не как способ разрушения объекта, а как средство абстрагирования от деталей этого процесса.

Или ты что-то другое имеешь в виду? Ну тогда поделись, как еще можно разрушить объект через указатель на его базовый класс.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: А когда может не вызываться деструктор?
От: Abyx Россия  
Дата: 25.01.13 15:28
Оценка: -1
Здравствуйте, rg45, Вы писали:

A>>это не может быть следствием, т.к. `delete pointer-to-base-type;` это не единственный способ корректно разрушить объект через указатель на его базовый класс.


R>Вероятно, ты имеешь ввиду технику, подобную той, которая применяется в shared_ptr? Ну так в ней разрушение объекта производится как раз через указатель most derived класса (при правильно использовании, при неправильном можно получить все то же UB). При этом сам shared_ptr я бы рассматривал не как способ разрушения объекта, а как средство абстрагирования от деталей этого процесса.


R>Или ты что-то другое имеешь в виду? Ну тогда поделись, как еще можно разрушить объект через указатель на его базовый класс.


да, удалять объект можно с помощью deleter'а с type-erasure как у shared_ptr,
причем *внезапно* shared_ptr<BaseClass> это *указатель* на базовый класс.

еще объект может владеть сам собой (встроенный счетчик ссылок и delete this, как например в COM),
объект может удалять какой-то GC (напр. Arena GC), впрочем это опять же deleter.

много в общем разных способов.
In Zen We Trust
Re[6]: А когда может не вызываться деструктор?
От: Abyx Россия  
Дата: 25.01.13 15:37
Оценка: -1
Здравствуйте, rg45, Вы писали:

A>>>>

A>>>>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
A>>>>Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.


R>Да, к сожалению, авторы статьи не дали четкого определения, что они понимают под полиморфным классом. Из общего контекста статьи можно догадаться, что они вкладывали в это понятие более широкий смысл — класс, объекты которого могут не только использоваться, но и удаляться через указатель базового класса (именно этому вопросу в статье уделено много внимания). Конечно же, это недочет, неточность формулировки, но еще не повод разбрасываться ярлыками типа "чушь" и "говносайт".


вот поэтому статья и говно, раз там написана чушь наподобие "раз полиморфный — значит ДОЛЖЕН быть виртуальный деструктор".
про весь сайт я может погорячился, хотя раз там есть статья такого качества — наверное и весь сайт такой.

у термина "полиморфный (класс)" есть вполне конкретное определение.
то что на это определение наложено ограничение, что объекты потомков такого класса будут удаляться через delete — это называется "более узкий смысл".
In Zen We Trust
Re[4]: А когда может не вызываться деструктор?
От: Abyx Россия  
Дата: 25.01.13 15:41
Оценка: -1
Здравствуйте, sts, Вы писали:

EP>>

EP>>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
EP>>Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.

EP>>Технически никому он ничего не должен, особенно если:
EP>>1. он protected
sts>тогда не получится "удалять через указатель на базовый класс"

не подменяйте тему.
в цитате написано не "удалять", а разрушать.
это разные вещи.
In Zen We Trust
Re[2]: А когда может не вызываться деструктор?
От: Abyx Россия  
Дата: 25.01.13 15:42
Оценка: -1
Здравствуйте, sts, Вы писали:

sts>Удаление неполного класса — одни из самых неприятных плюсовых граблей.

sts>Тоже деструктор pImpl не будет вызван.
sts>Лечится через unique_ptr (который не даст удалить неполный тип) и добавление ~Owner() туда, где Impl уже определен.

лечится включением предупреждений в компиляторе.
In Zen We Trust
Re: Разрушение компа прежде, чем будет разрушен объект, покатит? ;)
От: Erop Россия  
Дата: 25.01.13 15:43
Оценка: +1 :)
Здравствуйте, Аноним, Вы писали:

А>Какие могут быть ситуации, когда не вызывается дестуктор(сделал new и не сделал delete не в счет)?


на пример, если объёкт создали на компе, установленном на борут ГЧ, достигшей цели
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: А когда может не вызываться деструктор?
От: rg45 СССР  
Дата: 25.01.13 16:16
Оценка: +1
Здравствуйте, Abyx, Вы писали:

A>>>это не может быть следствием, т.к. `delete pointer-to-base-type;` это не единственный способ корректно разрушить объект через указатель на его базовый класс.


R>>Вероятно, ты имеешь ввиду технику, подобную той, которая применяется в shared_ptr? Ну так в ней разрушение объекта производится как раз через указатель most derived класса (при правильно использовании, при неправильном можно получить все то же UB). При этом сам shared_ptr я бы рассматривал не как способ разрушения объекта, а как средство абстрагирования от деталей этого процесса.


R>>Или ты что-то другое имеешь в виду? Ну тогда поделись, как еще можно разрушить объект через указатель на его базовый класс.


A>да, удалять объект можно с помощью deleter'а с type-erasure как у shared_ptr,

A>причем *внезапно* shared_ptr<BaseClass> это *указатель* на базовый класс.

A>еще объект может владеть сам собой (встроенный счетчик ссылок и delete this, как например в COM),

A>объект может удалять какой-то GC (напр. Arena GC), впрочем это опять же deleter.

A>много в общем разных способов.


Я понимаю, о чем ты говоришь, более того, сам придерживаюсь примерно тех же взглядов, и уже писал ранее по данной теме: http://rsdn.ru/forum/cpp/4071405.1
Автор: rg45
Дата: 09.12.10
. Как мне кажется, при изучении C++ вообще, и особенно таких вопросов как времени жизни объектов и владение, прежде чем приступать к вопросам дизайна и паттернам проектирования, нужно познакомиться с синтаксисом и базовыми концепциями C++ на несколько более низком уровне. Название сайта "C++ reference" несколько ввело меня в заблуждение — я подумал, что его авторы как раз и поставили перед собой задачу познакомить читателя с основами языка, поэтому и не удивился, что они достаточно узко рассматривают вопросы удаления объектов, не рассматривая других аспектов и возможных реализаций владения. Хотя, могли бы, с учетом того, что паттернам они таки уделяют некоторое внимание.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: А когда может не вызываться деструктор?
От: jazzer Россия Skype: enerjazzer
Дата: 25.01.13 16:22
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, jazzer, Вы писали:


J>>Здравствуйте, rg45, Вы писали:


A>>>>

A>>>>В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным.
A>>>>Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.


A>>>>это же чушь.


R>>>Это высказывание является прямым следствием из 5.3.5/3.


J>>
J>>struct A { virtual f(); ~A(); };
J>>struct B:A { f(); };

J>>int main()
J>>{
J>>  B b;
J>>  A* pa = &b;
  pa->>>f(); //полиморфный!
J>>}
J>>

J>>Здесь В замечательно обходится без виртуального деструктора и все корректно уничтожается, а 5.3.5/3 идет по градиенту.

R>Где в этом примере (цитирую) "разрушение объекта производного класса через указатель на соответствующий базовый класс" о котором шла речь выше?


Нету, в том-то и дело. Полиморфное использование есть, а полиморфного удаления нету.

R>Да, к сожалению, авторы статьи не дали четкого определения, что они понимают под полиморфным классом. Из общего контекста статьи можно догадаться, что они вкладывали в это понятие более широкий смысл — класс, объекты которого могут не только использоваться, но и удаляться через указатель базового класса (именно этому вопросу в статье уделено много внимания). Конечно же, это недочет, неточность формулировки, но еще не повод разбрасываться ярлыками типа "чушь" и "говносайт".


Ну, я конкретно не разбрасывался, но заявления типа "В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным." и "Cуществует правило — если базовый класс предназначен для полиморфного использования, то его деструктор должен объявляться виртуальным." являются слишком смелым обобщением, годным разве что для совсем начинающих, чтоб не отстрелили себе что-нть.

Правильная формулировка была бы такой: "если базовый класс предназначен для полиморфного использования удаления, то его деструктор должен объявляться виртуальным. Т.е. если ты не собираешься удалять объекты по голому указателю на базовый класс — нет необходимости делать деструктор виртуальным.

Например, есть у тебя std::map< std::string, std::shared_ptr<А> > — так вот в такую мапу ты вполне можешь запихивать указатели на В, и все будет правильно удаляться безо всяких виртуальных деструкторов (есть такое свойство у shared_ptr — deleter внутри него инициализируется в самом начале, и поэтому он знает, какой класс надо удалять).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: А когда может не вызываться деструктор?
От: sts  
Дата: 25.01.13 16:43
Оценка: -1
Здравствуйте, Abyx, Вы писали:

A>Здравствуйте, sts, Вы писали:


sts>>Удаление неполного класса — одни из самых неприятных плюсовых граблей.

sts>>Тоже деструктор pImpl не будет вызван.
sts>>Лечится через unique_ptr (который не даст удалить неполный тип) и добавление ~Owner() туда, где Impl уже определен.

A>лечится включением предупреждений в компиляторе.


что лечится ?
если включить предупреждения, то деструктор вызовется ?
не верю
Re[2]: Разрушение компа прежде, чем будет разрушен объект, покатит? ;)
От: sts  
Дата: 25.01.13 16:51
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Аноним, Вы писали:


А>>Какие могут быть ситуации, когда не вызывается дестуктор(сделал new и не сделал delete не в счет)?


E>на пример, если объёкт создали на компе, установленном на борут ГЧ, достигшей цели


так ведь и delete не успели сделатьт, так что это не в счет
Re[3]: Разрушение компа прежде, чем будет разрушен объект, покатит? ;)
От: Erop Россия  
Дата: 25.01.13 17:02
Оценка:
Здравствуйте, sts, Вы писали:

А>>>Какие могут быть ситуации, когда не вызывается дестуктор(сделал new и не сделал delete не в счет)?


E>>на пример, если объёкт создали на компе, установленном на борут ГЧ, достигшей цели


sts>так ведь и delete не успели сделатьт, так что это не в счет

Ты ТС или просто рассуждаешь?
Я так понял, что ТС спросил, когда может так получится, что у созхданного С++ объекта не будет вызван деструктор. при этом случай с забытым delete, он считал тривиальным и просил на него не отвлекаться. на этот вопрос я и ответил...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.