Alexander "SonnySlave"
😂😂😂
Vsevolod
вообще, это очень сложный вопрос
Vsevolod
чтобы созданный объект сам хранил рефренс на себя
Vsevolod
я это когда-то давно делал через всякие enable_shared_from_this и самоотстрел специальным методом
🐙 Antony
чтобы созданный объект сам хранил рефренс на себя
Вы про weak_ptr? Или объект хранит именно shared_ptr на самого себя, и когда надо умереть, делает shared_ptr_var.reset() ?
Vsevolod
я делал с shared, то есть, объект создается через метод, возвращающий std::shared_ptr<T> (с приватным конструктором) и хранит внутри себя этот shared_ptr, пока ему нужно существовать вне зависимости от внешнего мира
Vsevolod
а когда это не нужно - зовет reset, да
Vsevolod
если внешнему миру это тоже не нужно, то все подыхает
Anatoly
кто-то сохраняет weak_ptr, сам диалог примешивает вот такую фигню в виде SharedPtrReady и когда диалог умрет, weak_ptr сможет это определить: struct SharedPtrEmptyDeletor { template<class T> void operator()(T* p) const { } }; template<typename T> struct SharedPtrReady : public std::enable_shared_from_this<T> { public: SharedPtrReady() : fake_shared_ptr_(self(), SharedPtrEmptyDeletor()) { } protected: T* self() { return static_cast<T*>(this); } private: std::shared_ptr<T> fake_shared_ptr_; };
🐙 Antony
а когда это не нужно - зовет reset, да
Вы ведь понимаете, что это лютое UB?
Vsevolod
почему? доступ делается через один и тот же control block всегда
🐙 Antony
Запустите под санитайзерами ваш код, в тот момент, кодга this - единственный владелец shared_ptr
Vsevolod
я не понимаю, откуда здесь может взяться UB, если класс делается через enable_shared_from_this
Vsevolod
а в delete this что плохого?
Vsevolod
тоже валидное использование, если потом не дергать этот this (в т.ч. не вызывая нестатические методы)
Anatoly
@antoshkka @berkus Вообщем ситуация там такая: создано немодальное Windows окно, единственная связь с миром C++ это void* во вспомогательной структуре класса окна. Когда окно закрывается пользователем, С++ объект, ассоциированный с этим окном, должен быть уничтожен. Этот С++ объект подписывается на событие "последнегого выдоха господина пж" и убивает себя через delete this. Такова дислокация.
Alexander "SonnySlave"
тоже валидное использование, если потом не дергать этот this (в т.ч. не вызывая нестатические методы)
Это не этот кейс? (не читал весь тред) Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. [...] If the object will be or was of a class type with a non-trivial destructor, and the pointer is used as the operand of a delete-expression, the program has undefined behavior.
Anatoly
А держать shared_ptr в обработчике события нельзя?
по сути это call_back функция, вызываемая потрохами windows
Anatoly
Ну, Ильюха, много людей Windows даже в глаза не видели
🐙 Antony
Ок, со стороны shared_ptr подлянки в виде бесконечной рекурсии не будет void shared_ptr::reset() noexcept; Effects: Equivalent to shared_ptr().swap(*this).
🐙 Antony
Дык Qt же. Там это не так убого реашается, ибо можно shared_ptr держать в коллбеке, и если владелец колбека будет уничтожен, вузовется деструктор shared_ptr и ресурс не утечёт
🐙 Antony
unordered_map<Handle, shared_ptr<MyClass> > open_windows_to_kill_without_holding_sp_in_this; Такая конструкция поможет избежать вызова delete this?
🐙 Antony
Хай обоснован тем, что в мире с исключениями ручное управление памятью и ресурсами есть зло
Matwey
Господа, а можно ли как-то эту порнографию редуцировать, не используя препроцессор? struct width_visitor: public boost::static_visitor<std::size_t> { template<class T> std::size_t operator() (const image<T>& i) const { return i.width(); } }; struct height_visitor: public boost::static_visitor<std::size_t> { template<class T> std::size_t operator() (const image<T>& i) const { return i.height(); } }; struct depth_visitor: public boost::static_visitor<std::size_t> { template<class T> std::size_t operator() (const image<T>& i) const { return i.depth(); } };
Matwey
http://en.cppreference.com/w/cpp/utility/variant/visit
У меня нет дженерик лямбд :(
Anatoly
Хай обоснован тем, что в мире с исключениями ручное управление памятью и ресурсами есть зло
ну в контексте WINAPI я не имею право выпустить ниодного исключения, находясь в обработчике Windows события, к тому же delete this будет последнее, что мир запомнит об этом объекте
Matwey
Мало информации о роде порнографии, но Ванга спрашивает, может удастся использовать ссылки на методы?
Ну я не представляю существует ли такая синтаксическая конструкция как ссылка на метод неинстанцированного шаблона. &image<???>::width
Дмитрий
А в какой момент ты собираешься создавать объекты типа depth_visitor, например?
Matwey
Всё, как завещали нам авторы бубсов: boost::apply_visitor(width_visitor{}, x);
Дмитрий
вот в этот момент нельзя взять адрес метода?
Matwey
ммм... нет. ведь я не знаю какой именно тип хранится в варианте
Berkus
@MasterZiv ^ вот твой кейс про окно
Berkus
выше почитай
🐙 Antony
https://github.com/boostorg/beast/blob/develop/example/advanced/server-flex/advanced_server_flex.cpp#L278
Это как раз нормально - там shared_ptr держится колбеком, а не в this. В случае шибки выполнится коллбек, завершится, а потом вызовется деструктор shared_ptr (уже не из метода класса)
Александр
Александр
То, что Антон процитировал
Anatoly
7 постов вверх
я не понял как это применимо к "оконной" проблеме, описанной выше
Александр
я не понял как это применимо к "оконной" проблеме, описанной выше
Я сам не смотрел код beast, но походу там "объект сам управляет временем своей жизни" без delete this
Anatoly
Я сам не смотрел код beast, но походу там "объект сам управляет временем своей жизни" без delete this
Схематично код, создающий немодальное окно, выглядит так: auto wnd = std::make_unique<MyWindow>(); if( wnd->Create(... ) ) { wnd->Show (); wnd.reset(); }
Anatoly
как я писал выше через фиктивный shared_ptr?
Anatoly
покажи полный пример, нифига не пойму о чем вы говорите
Anatoly
откуда возьмется shared_ptr и кем он будет кипится?
Alexander "SonnySlave"
люди так не считают.
Alexander "SonnySlave"
не надо перевирать. Люди считают delete this невалидным в случае, который я кидал выше
Andrei
люди так не считают.
в @supapro парень именно так и думал, когда задавал вопрос. а это уже дальше разговор перешл из разряда "неправильно в с++" до "неправильно в дизайне"
Oleg
delete this - это как goto. Лучше не использовать, но если знаешь что и зачем - то пожалуйста
🐙 Antony
Я до сих пор это подозреваю... но доказать не могу :)
Anatoly
Схематично код, создающий немодальное окно, выглядит так: auto wnd = std::make_unique<MyWindow>(); if( wnd->Create(... ) ) { wnd->Show (); wnd.reset(); }
Anatoly
@berkus @antoshkka ребята, вот пример, при закрытии окна пользователем объект MyWindow должен уйти в мир иной.
Andrei
а при delete this вызывается только деструктор или память осводобится тоже?
Egor
а при delete this вызывается только деструктор или память осводобится тоже?
И память освободится. Деструктор явно вызывается как любой другой метод
Andrei
И память освободится. Деструктор явно вызывается как любой другой метод
хм, тогда например в этом случае не будет утечки? X *x = new X; x->custom_delete(); а в custom_delete происходит delete this. x и this необязательно же должны совпадать
Egor
хм, тогда например в этом случае не будет утечки? X *x = new X; x->custom_delete(); а в custom_delete происходит delete this. x и this необязательно же должны совпадать
Не будет. x и this в этом случае обязаны совпадать по определению this — это в точности указатель на объект, у которого вызван метод.
Andrei
Не будет. x и this в этом случае обязаны совпадать по определению this — это в точности указатель на объект, у которого вызван метод.
точно, не подумал. тогда ведь получается, что можно указать пользователю обязательно создавать переменные в куче, например, убрав деструктор из видимости. Только, для чего это полезно, мне неведомо
Anatoly
хм, тогда например в этом случае не будет утечки? X *x = new X; x->custom_delete(); а в custom_delete происходит delete this. x и this необязательно же должны совпадать
delete this и деструктор вызовет и освободит, и это последнее, что можно сделать с этим указателем, все остальное UB
Andrei
а это когда полезно?
Andrei
как раз я думал, может ты сталкивался в работе с ситуацией, когда можно было это применить, или где-то читал. философски понятно, а вот на практике увидеть интересно
Berkus
идиома должна называеться goto delete this;
Berkus
@berkus @antoshkka ребята, вот пример, при закрытии окна пользователем объект MyWindow должен уйти в мир иной.
закрытие окна - это операция которую осуществляет "кто-то", вон он пусть и удаляет
Anatoly
закрытие окна - это операция которую осуществляет "кто-то", вон он пусть и удаляет
на пути у пользователя только оконный менеджер, именно он уничтожает окно в системе, мне же приходит жалкий WM_DESTROY
Anatoly
у тебя тоже в аппе есть буккипинг этих самых окон
ее нет, указатель на C++ в мембере WNDCLASS-а операционной системы
Anatoly
WM_NCDESTROY
да, Костя, но не в этом суть
Constantine
это гарантированно последнее сообщение
Constantine
вы обсуждаете delete this там или что?
Anatoly
да
Constantine
кажется если объект захватывает ресурс, которым не может на самом деле управлять, это даже адекватно
Constantine
хотя я все равно переживаю, когда объект суидится, имея вызов в стеке