首页 > 如何在自己实现shared_ptr时,使得定义的shareda_ptr类模板可以接受一个可调用对象?

如何在自己实现shared_ptr时,使得定义的shareda_ptr类模板可以接受一个可调用对象?

template <typename T>
class shared_ptr {
public:
    shared_ptr(): p(nullptr), use(new std::size_t(1)) { }
    explicit shared_ptr(T *pt): p(pt), use(new std::size_t(1)) {    }
    shared_ptr(const shared_ptr &sp): p(sp.p), use(sp.use) { if (use) ++*use; }
    shared_ptr& operator=(const shared_ptr&);
    ~shared_ptr();
    T& operator*() { return *p; }
    const T& operator*() const { return *p; }
private:
    T *p;
    std::size_t *use;
};

template <typename T>
shared_ptr<T>::~shared_ptr() {
    if (use && 0 == --*use) {
        delete p;   // del ? del(p) : delete p;
        delete use;
    }
}

如上所示。是C++ Primer 第五版16.1.6节的一个问题,请问我应该给shared_ptr类增加一个什么类型的成员del,才能够使得这个类可以接受一个可调用对象,此对象的目的是清理动态内存分配的指针,但是可以自定义这个对象的行为。
谢谢!


可以参考一下。。。

template <typename Tp>
class AutoCleanHelperBase
{
public:
    AutoCleanHelperBase(Tp* ptr)
        :m_ptr(ptr)
    { }

    virtual void destroy()
    {}

protected:
    Tp* m_ptr;
};

template <typename Tp, typename Deleter>
class AutoCleanHelper;

template <typename Tp>
class AutoCleanHelper<Tp, void> : public AutoCleanHelperBase<Tp>
{
public:
    AutoCleanHelper(Tp* ptr)
        :AutoCleanHelperBase<Tp>(ptr)
    { }

    void destroy()
    {
        delete this->m_ptr;
    }
};

template <typename Tp, typename Deleter>
class AutoCleanHelper: public AutoCleanHelperBase<Tp>
{
public:
    AutoCleanHelper(Tp* ptr, Deleter del)
        :AutoCleanHelperBase<Tp>(ptr)
        ,m_del(del)
    { }

    void destroy()
    {
        (this->m_ptr->*m_del)();
    }

private:
    Deleter m_del;
};

template <typename Tp>
class AutoClean
{
public:
    template <typename Tp1>
    AutoClean(Tp1* ptr)
        :m_helper(new AutoCleanHelper<Tp1, void>(ptr))
    {}

    template <typename Tp1, typename Deleter>
    AutoClean(Tp1* ptr, Deleter deleter)
        :m_helper(new AutoCleanHelper<Tp1, Deleter>(ptr, deleter))
    {}

    ~AutoClean()
    {
        m_helper->destroy();
        delete m_helper;
    }

private:
    AutoCleanHelperBase<Tp>* m_helper;
};

class CanDestroy
{
public:
    ~ CanDestroy()
    {
        std::cout <<"I'm destroy now !!!\n";
    }
};

class ExplicitDestroy
{
public:
    void destroy()
    {
        std::cout <<"I'm also destroy now !!!\n";
    }
};

int main()
{
    AutoClean<CanDestroy> clean1(new CanDestroy);

    AutoClean<ExplicitDestroy> clean2(new ExplicitDestroy, &ExplicitDestroy::destroy);

    return 0;
}

可在shared_ptr里维护一个类型为void (*)(T*)的函数指针,然后在需要释放内存的时候调一下这个函数。一个简单的例子:

void release(somePointer* ptr) {
    delete ptr;
    ptr = nullptr;    
}

我太天真了=,-,你可以看看这个回答 关于c++中,shared_ptr中的删除器


参考了araraloren的回答,感谢!

template <typename T>
class Contents {
public:
    Contents(T* pt): contents(pt) { }
    virtual void destory() {    }
protected:
    T* contents;
};

template <typename T, typename D>
class ContentsWithDeleter;

template <typename T>
class ContentsWithDeleter<T, void> : public Contents<T> {
public:
    ContentsWithDeleter(T *pt): Contents<T>(pt) {  }
    void destory() override { delete this->contents; }
};

template <typename T, typename D>
class ContentsWithDeleter : public Contents<T> {
public:
    ContentsWithDeleter(T *pt, D del): Contents<T>(pt), deleter(del) {  }
    void destory() override { deleter(this->contents); }
private:
    D deleter;
};

template <typename T>
class shared_ptr {  // todo
public:
    template <typename Tp>
    shared_ptr(Tp *ptr): p(new ContentsWithDeleter<Tp, void>(ptr)), use(new std::size_t(1)) { }
    template <typename Tp, typename D>
    shared_ptr(Tp *ptr, D del): p(new ContentsWithDeleter<Tp, D>(ptr, del)), use(new std::size_t(1)) {    }
    shared_ptr(const shared_ptr &sp): p(sp.p), use(sp.use) { if (use) ++*use; }
    shared_ptr& operator=(const shared_ptr&);
    ~shared_ptr();
    T& operator*() { return *p; }
    const T& operator*() const { return *p; }
private:
    Contents<T> *p;
    std::size_t *use;
};

template <typename T>
shared_ptr<T>::~shared_ptr() {
    if (use && 0 == --*use) {
        p->destory();   // del ? del(p) : delete p;
        delete p;
        delete use;
    }
}

template <typename T>
shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T> &rhs) {
    if (rhs.use) ++*rhs.use;
    if (use && 0 == --*use) {
        p->destory();
        delete p;
        delete use;
    }
    p = rhs.p;
    use = rhs.use;
    return *this;
}
【热门文章】
【热门文章】