Поведение std::unique_ptr
с custom deleter
основано на статическом типе средства удаления. Отсутствие полиморфизма, никакого поведения во время выполнения, основанного на фактическом удаленном средстве, переданном во время выполнения, поскольку предоставленный производный удалитель подразделяется на статический тип объявленного удалителя.
(Он предназначен специально для того, чтобы размер unique_ptr с default deleter
или с custom deleter without any data members
имел тот же размер, что и необработанный указатель).
статическое поведение unique_ptr
с custom deleter
:
class A {};
struct BaseDeleter {
virtual void operator()(A* p) const {
std::cout << "in BaseDeleter" << std::endl;
delete p;
}
};
struct DerivedDeleter: BaseDeleter {
void operator()(A* p) const override {
std::cout << "in DerivedDeleter" << std::endl;
delete p;
}
};
int main() {
auto unique_var = std::unique_ptr<A, BaseDeleter>(new A);
unique_var = std::unique_ptr<A, DerivedDeleter>(new A);
}
Вывод:
in BaseDeleter
in BaseDeleter
Это в отличие от std::shared_ptr
, который по-своему хранит свое собственное средство удаления и допускает динамическое поведение:
динамическое поведение shared_ptr
с custom deleter
:
int main() {
auto shared_var = std::shared_ptr<A>(new A, BaseDeleter{});
shared_var = std::shared_ptr<A>(new A, DerivedDeleter{});
}
Выход:
in BaseDeleter
in DerivedDeleter
Код: https://coliru.stacked -crooked.com / a / 54a8d2fc3c95d4c1
Поведение присваивания std::unique_ptr
с разными custom deleter
на самом деле нарезка .
Почему unique_ptr не предотвращает нарезку пользовательского удалителя?
Почему язык не заблокировал присвоение std::unique_ptr
, если назначенный unique_ptr имеет другое custom deleter
, чтобы избежать нарезки?
Это представляется возможным, как показано ниже.
Блокировка unique_ptr
от нарезки custom deleter
template<typename TYPE, typename Deleter>
struct my_unique_ptr : std::unique_ptr<TYPE, Deleter> {
using BASE = std::unique_ptr<TYPE, Deleter>;
using std::unique_ptr<TYPE, Deleter>::unique_ptr;
auto& operator=(std::nullptr_t) noexcept {
return BASE::operator=(nullptr);
}
template<typename T, typename OtherDeleter,
std::enable_if_t<!std::is_same<OtherDeleter, Deleter>::value>* dummy = nullptr>
auto& operator=(std::unique_ptr<T, OtherDeleter>&& other) = delete;
};
Код: http://coliru.stacked -crooked.com / a / 089cd4c7303ad63e