问题描述
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,才能够使得这个类可以接受一个可调用对象,此对象的目的是清理动态内存分配的指针,但是可以自定义这个对象的行为。谢谢!
问题解答
回答1:可以参考一下。。。
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;}回答2:
可在shared_ptr里维护一个类型为void (*)(T*)的函数指针,然后在需要释放内存的时候调一下这个函数。一个简单的例子:
void release(somePointer* ptr) { delete ptr; ptr = nullptr; }
我太天真了=,-,你可以看看这个回答 关于c++中,shared_ptr中的删除器
回答3:参考了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 { // todopublic: 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;}