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'
s
X
对象得到共享

试着这样做:

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));
}