有没有办法在现有的shared_ptr实例上更改删除操作

Gre*_*jan 8 c++

我有一个功能,我希望在90%的时间内完成清理操作,但在10%中我想要完成其他一些操作.

有没有办法使用一些标准的范围控制,shared_ptr<>以便最初它可以有一个删除操作,然后在函数中可以更改删除操作?

shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );
ptr.pn.d = std::mem_fun_ref(&T::queueMe);
Run Code Online (Sandbox Code Playgroud)

smi*_*syn 10

并非如此 - 标准的shared_ptr编写方式是Deleter可以按值存储在控制节点(包含引用计数器、保存删除器、跟踪弱指针等的特殊对象)中。删除器是类型擦除的,但如果您以某种方式知道具体的删除器类型,则可以使用std::get_deleter<Deleter>(ptr). 有了它,您可以访问删除器并更改其状态。例子:

struct A {};

struct deleter {
    void operator()(A* a) {delete a; }
    int m_state;
};

std::shared_ptr<A> ptr(new A(), deleter{});

std::get_deleter<deleter>(ptr)->m_state = 5;
Run Code Online (Sandbox Code Playgroud)

如果您仅对所有删除器使用函数指针,那么您可以完全替换它,因为所有潜在的删除器都使用相同的签名。

(是的,我知道这个问题已经有 9 年历史了,但我在 2020 年才遇到这个问题,并像这样解决了它。其可能的原因是包装了通过原始指针管理所有权的遗留代码中的 C 指针和对象)


ere*_*eOn 2

shared_ptr我认为删除程序一旦创建就无法更改。

但你为什么要这么做呢?通常,当您创建一个对象时,您立即知道必须如何销毁它。这不太可能改变。

如果您确实必须执行一些特定的处理,您仍然可以提供一个自定义删除器,它根据所需的逻辑执行特殊的操作。

  • 我刚刚想到了一个原因,那就是您可能想用一个新的删除器替换旧的删除器,*和*其他东西(例如通知侦听器对象销毁)。但我很确定这是不可行的,因为删除器位于控制块中,所以您当然不能用不同大小的删除器替换它。所以就像你说的,这种行为的潜力需要从一开始就存在于“shared_ptr”中。 (2认同)