Информация об изменениях

Сообщение Re: shared_ptr/make_shared и делитер, довесить доп обработку от 28.03.2024 21:32

Изменено 28.03.2024 21:34 watchmaker

Re: shared_ptr/make_shared и делитер, довесить доп обработку
Здравствуйте, пффф, Вы писали:


П>Насколько я знаю, можно создать shared_ptr, не заботясь о виртуальности деструктора — там есть делитер, который правильно вызывает деструктор конкретного класса, и тут есть возможность задать свой делитер.

Да

П>При создании shared_ptr можно задать свой делитер, но если использовать make_shared — то вроде делитер уже нельзя задать. Или таки как-то можно?


У make_shared одна из ролей (и главная оставшаяся в современном С++) — экономить число аллокаций.
И если make_shared выделяет в памяти один блок, который хранит и счётчик, и объект, то и для удаления такого блока нужно иметь определённый deleter, который знает как его удалять.
А если ты хочешь добавить ещё и свой deleter, то получается у объекта будут сразу два разных deleter'a? Как ты себе такое представляешь? Такое вообще никогда работать не будет: ни с shared_ptr, ни в других ситуациях.

П>Суть вопроса: у меня везде используется make_shared, и в какой-то момент мне понадобилось при удалении объекта произвести какие-то дополнительные действия. ... хочется иметь опциональную возможность навешивать доп действие при удалении объекта, которым рулит shared_ptr, или не навешивать, а использовать дефолтное разрушение.


Не нужен тебе для этого deleter. Делай свои действия в деструкторе, или в scope_exit или в аналоге.



П> В раскладку объекта влезать нет возможности, чтобы что-то туда добавить, что могло бы управлять моим ресурсом


Не нужно в объект влезать. Положи свои действия в обёртке рядом с ним.
Да даже сам make_shared<T> точно так же поступает: он же не влезает в раскладку объекта T чтобы добавить в него интрузивные счётчики, а вместо этого (обычно) просто делает структуру, в которое хранятся в соседних полях и контрольные блоки, и пользовательский объект T. И создаёт уже такая структура в памяти. А потом пользователю возвращает указатель на подполе этой структуры, где объект типа T лежит.
Делай точно так же.
scope_exit и make_shared можно свободно комбинировать — они ортогональные.
И aliasing constructor тебе в помощь.
Re: shared_ptr/make_shared и делитер, довесить доп обработку
Здравствуйте, пффф, Вы писали:


П>Насколько я знаю, можно создать shared_ptr, не заботясь о виртуальности деструктора — там есть делитер, который правильно вызывает деструктор конкретного класса, и тут есть возможность задать свой делитер.

Да

П>При создании shared_ptr можно задать свой делитер, но если использовать make_shared — то вроде делитер уже нельзя задать. Или таки как-то можно?


У make_shared одна из ролей (и главная оставшаяся в современном С++) — экономить число аллокаций.
И если make_shared выделяет в памяти один блок, который хранит и счётчик, и объект, то и для удаления такого блока нужно иметь определённый deleter, который знает как его удалять.
А если ты хочешь добавить ещё и свой deleter, то получается у объекта будут сразу два разных deleter'a? Как ты себе такое представляешь? Такое вообще никогда работать не будет: ни с shared_ptr, ни в других ситуациях.

П>Суть вопроса: у меня везде используется make_shared, и в какой-то момент мне понадобилось при удалении объекта произвести какие-то дополнительные действия. ... хочется иметь опциональную возможность навешивать доп действие при удалении объекта, которым рулит shared_ptr, или не навешивать, а использовать дефолтное разрушение.


Не нужен тебе для этого deleter. Делай свои действия в деструкторе, или в scope_exit или в аналоге.



П> В раскладку объекта влезать нет возможности, чтобы что-то туда добавить, что могло бы управлять моим ресурсом


Не нужно в объект влезать. Положи свои действия в обёртке рядом с ним.
Да даже сам make_shared<T> точно так же поступает: он же не влезает в раскладку объекта T чтобы добавить в него интрузивные счётчики, а вместо этого (обычно) просто делает структуру, в которой хранятся в соседних полях и контрольный блок, и пользовательский объект T. И создаёт уже такую структуру в памяти. А потом пользователю возвращает указатель на подполе этой структуры, где объект типа T лежит.
Делай точно так же.
scope_exit и make_shared можно свободно комбинировать — они ортогональны.
И aliasing constructor тебе в помощь.