Я плохо знаю про современные плюсики, изучаю методом тыка в основном
Насколько я знаю, можно создать shared_ptr, не заботясь о виртуальности деструктора — там есть делитер, который правильно вызывает деструктор конкретного класса, и тут есть возможность задать свой делитер.
При создании shared_ptr можно задать свой делитер, но если использовать make_shared — то вроде делитер уже нельзя задать. Или таки как-то можно?
Суть вопроса: у меня везде используется make_shared, и в какой-то момент мне понадобилось при удалении объекта произвести какие-то дополнительные действия. В раскладку объекта влезать нет возможности, чтобы что-то туда добавить, что могло бы управлять моим ресурсом, хочется иметь опциональную возможность навешивать доп действие при удалении объекта, которым рулит shared_ptr, или не навешивать, а использовать дефолтное разрушение.
Какие есть варианты?
Re: shared_ptr/make_shared и делитер, довесить доп обработку
Здравствуйте, пффф, Вы писали:
П>Насколько я знаю, можно создать shared_ptr, не заботясь о виртуальности деструктора — там есть делитер, который правильно вызывает деструктор конкретного класса, и тут есть возможность задать свой делитер. П>При создании shared_ptr можно задать свой делитер, но если использовать make_shared — то вроде делитер уже нельзя задать. Или таки как-то можно?
Кастомный делитер в make_shared не передать. Поэтому либо руками звать к-тор шаред-поинтера, либо сделать производный класс, в д-торе которого делать что тебе потребно. Тогда можно продолжать использовать make_shared.
_____________________
С уважением,
Stanislav V. Zudin
Re: shared_ptr/make_shared и делитер, довесить доп обработку
Здравствуйте, пффф, Вы писали: П>При создании shared_ptr можно задать свой делитер, но если использовать make_shared — то вроде делитер уже нельзя задать. Или таки как-то можно? П>Какие есть варианты?
Я бы сделал свою функцию make_shared_my_del, которая возвращает std::shared_ptr с нужным делитером.
Реализация тривиальная с использованием std::forward.
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 тебе в помощь.
Здравствуйте, пффф, Вы писали:
П>Насколько я знаю, можно создать shared_ptr, не заботясь о виртуальности деструктора — там есть делитер, который правильно вызывает деструктор конкретного класса, и тут есть возможность задать свой делитер. П>При создании shared_ptr можно задать свой делитер, но если использовать make_shared — то вроде делитер уже нельзя задать. Или таки как-то можно?