C++ C++;自定义删除链接?
我有一个带有自定义删除器的共享指针,并希望使用自定义删除器从中创建另一个共享指针,该自定义删除器在调用原始自定义删除器之前执行一些工作。类似于C++ C++;自定义删除链接?,c++,C++,我有一个带有自定义删除器的共享指针,并希望使用自定义删除器从中创建另一个共享指针,该自定义删除器在调用原始自定义删除器之前执行一些工作。类似于 std::shared_ptr<X> foo; { std::shared_ptr<X> bar(new X(), Deleter); foo.reset(bar, My_Deleter(bar.get_deleter())); } std::shared_ptr foo; { std::共享_ptr条(新的
std::shared_ptr<X> foo;
{
std::shared_ptr<X> bar(new X(), Deleter);
foo.reset(bar, My_Deleter(bar.get_deleter()));
}
std::shared_ptr foo;
{
std::共享_ptr条(新的X(),删除器);
重置(bar,My_Deleter(bar.get_Deleter());
}
当bar超出范围时,就不会因为foo而发生任何事情。当foo超出范围时,我的Deleter将运行,然后调用Deleter
可以像这样链接自定义删除程序吗?My_Deleter在构造时存储Deleter的副本,但我不确定类型声明是什么样子。因为共享_内存的Deleter只能在内存分配时安全地设置,所以无法完成。不同的共享\u ptr不能有不同的删除器。为了响应在超出范围之前做一些工作(另一个删除程序的原因),如果您想在删除它之前做一些额外的工作,那么您可以调用一个单独的函数,该函数将在范围结束之前完成工作。在离开之前,检查一些你可能想要的条件,并完成这些工作 调用
shared\u ptr::get\u deleter()
时必须指定deleter类型,因此必须相应地专门化自定义delete类
我不确定您是否可以将shared_ptr
对象传递给reset()
。它需要一个新的T*
指针作为输入,shared\u ptr
不能隐式转换为T*
,AFAIK。只有构造函数、operator=()
和swap()
方法允许将shared\u ptr
作为调用共享的输入。政府甚至警告说:
如果ptr指向的对象已经拥有,该函数将导致未定义的行为。
因此,您必须使用operator=
或swap()
将bar
分配给foo
,以便bar'
sX
对象得到共享
试着这样做:
template <typename T, class Deleter = std::default_delete<T> >
class My_Deleter
{
Deleter *chained_deleter;
My_Deleter(std::shared_ptr<T>& p)
: chained_deleter(std::get_deleter<Deleter>(p));
{
}
void operator()(T *ptr) const
{
//...
if (chained_deleter)
(*chained_deleter)(ptr);
}
};
模板
类我的删除器
{
删除器*链式删除器;
我的删除器(标准::共享\u ptr&p)
:链式删除器(std::get_deleter(p));
{
}
void运算符()(T*ptr)常量
{
//...
如果(链接删除器)
(*链式删除器)(ptr);
}
};
std::shared_ptr foo;
{
std::共享的ptr条(新的X,删除器);
foo=std::shared_ptr(bar,My_Deleter(bar));
}
但不确定这是否真的有效。这取决于当与不同的删除器共享同一对象指针时,共享的\u ptr是否/如何保留原始删除器。我有一种感觉,当
bar
的原始Deleter
超出范围且无法安全链接时,它可能会丢失。而不是std::shared_ptr bar=new X()
,你的意思是std::shared_ptr bar{new X(),Deleter{}代码>?(shared_ptr
只有一个模板参数;删除器的类型被删除)是的,语法错误。下面的回答很好。我需要做的是让我的\u Deleter使用一个成员变量来保存原始共享\u ptr的副本,并将Deleter作为其自定义Deleter,然后创建一个新的共享\u ptr,将我的\u Deleter作为其自定义Deleter。例如foo.reset(bar.get(),My_Deleter(bar))。当foo超出作用域时,它将运行My_Deleter,它可以将其成员重置为运行Deleter。好的,但是既然删除器是类型擦除的,那么将副本保存到Deleter的My_Deleter的成员会是什么样子?我不认为您可以将std::shared_ptr
对象传递到reset()
。它需要一个新的T*
指针作为输入,并且shared\u ptr
不能隐式转换为T*
,对吗?。此外,只有shared\u ptr
的构造函数和operator=
才允许将std::shared\u ptr
作为输入来调用适当的共享。您链接到的reset()
引用甚至对此发出警告:“如果ptr
指向的对象已经拥有,该函数将导致未定义的行为。”@RemyLebeau您是对的,我无意中读到了这一行。如果重置不是将点链接到对象的安全方式,我不确定是否有办法做到这一点。查看文档,您只能在内存分配时设置删除器,这意味着您不能根据指向它的指针拥有单独的删除器。对不起,犯了那个严重的错误!更新答案。
std::shared_ptr<X> foo;
{
std::shared_ptr<X> bar(new X, Deleter);
foo = std::shared_ptr<X>(bar, My_Deleter<X, decltype<Deleter> >(bar));
}