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

时间:2010-07-09 17:20:45

标签: 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);

5 个答案:

答案 0 :(得分:2)

创建shared_ptr后,我认为您无法更改删除。

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

如果你真的必须做一些特定的治疗,你仍然可以提供一个自定义删除器,根据所需的逻辑做特殊事情。

答案 1 :(得分:2)

有正当理由需要更改删除器。以此为例:

val1=2
val2=1
wb = load_workbook(os.path.abspath(os.path.join(os.path.dirname(__file__),'c:\ExcelData\pyExcel.xlsx')))
sheet = wb.get_sheet_by_name('Sheet1')
c = sheet.cell(row=val1, column=val2).value
d = sheet.cell(row=val2, column=val2).value
print(c) 
print(d)

在这种情况下,foo()函数使用一些特殊的分配器来分配double *。它还需要以特殊方式释放内存。调用者不应该知道如何释放内存。

答案 2 :(得分:2)

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

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;

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

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

答案 3 :(得分:1)

#include <iostream>
#include <memory>
#include <functional>

struct A {
    ~A() {
        std::cout << "~A()" << std::endl;
    }
};

using DeleterCb = std::function<void(A* p)>;

struct ADeleter {
 public:
    explicit ADeleter(DeleterCb cb) :
        mDeleterCb(cb) {}
    ADeleter() = delete;
    ~ADeleter() = default;

    void operator()(A *a) {
        mDeleterCb(a);
    }
    
    void setDeleterCb(DeleterCb cb) {
        mDeleterCb = cb;
    }

 private:
    DeleterCb mDeleterCb;
};

int main() {
    auto sp = std::shared_ptr<A>(new A{},
        ADeleter([](A *p){
            delete p;
            std::cout << "deleter_1" << std::endl;
        })
    );
    
    std::get_deleter<ADeleter>(sp)->setDeleterCb(
        [](A *p){
            delete p;
            std::cout << "deleter_2" << std::endl;
        }
    );
}

答案 4 :(得分:0)

这没有任何意义,因为有shared_ptr个任意数量的shared_ptr来管理价值的所有权。你需要全部修改它们,这是不可行的。我们不要忘记控制块是一个实现细节,所以去“aha,但在控制块中更改它”将不起作用。

删除操作应由class C { ... void (C::action*)() { &C::action1 }; void action1(); void action2(); ~C() { (this->*action)(); } }; void test() { std::shared_ptr<C> a; a->action = &C::action2; // action2 gets invoked once `a` falls out of scope } 拥有的实例控制,例如

if [ -z $SSH_AUTH_SOCK ]; then
    if [ -r ~/.ssh/env ]; then
            source ~/.ssh/env
            if [ `ps -p $SSH_AGENT_PID | wc -l` = 1 ]; then
                    rm ~/.ssh/env
                    unset SSH_AUTH_SOCK
            fi
    fi
fi

if [ -z $SSH_AUTH_SOCK ]; then
    ssh-agent -s | sed 's/^echo/#echo/'> ~/.ssh/env
    chmod 600 ~/.ssh/env
    source ~/.ssh/env > /dev/null 2>&1
fi