首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >引用计数智能指针类

引用计数智能指针类
EN

Code Review用户
提问于 2013-04-18 08:21:23
回答 2查看 705关注 0票数 3

我做了一个引用计数智能指针类。我的目标是用适当的文档创建一个“最小”但“通用”的智能指针类。这基本上是为了教育目的。

我想有一些关于异常处理、代码清晰性、注释、API的易用性等方面的评论,如果代码是“工业级别”的话,我也会发表评论。

代码语言:javascript
复制
#ifndef SMARTPTR_HPP
#define SMARTPTR_HPP

#include <algorithm>

namespace smartptrnamespace
{

//
// Basic reference counting smart pointer (no overloaded Bool magic, etc).
// Ownership of memory on heap is shared amongst objects of this
// class (shared ownership) i.e., no new object of T type is created
// by this class.
// Objects of this class are:
//  1. nothrow-copy-assignable
//  2. nothrow-copy-constructible
//  3. nothrow-destructible, if T is nothrow-destructible
//  4. suitable for storage in a STL container like List, Deque etc.
// Strong exception guarantee
//
// Sample Usage:
//  SmartPtr<T> sPtr1 (new T);  // sPtr1 refers to object of T type
//  SmartPtr<T> sPtr2;          // sPtr2 refers to no object
//  if (!sPtr2.isAssigned ())   // SmartPtr::isAssigned() returns false if no reference is being held
//      cout << "sPtr2 is not holding any reference" << endl;
//  sPtr2 = new T;              // make a new oject of T and pass ownership to sPtr
//
template<class T>
class SmartPtr
{
    public:

        // create a new object which is not
        // refering to any object on heap.
        // no-throw guarantee
        explicit SmartPtr ()
            :   m_pT (NULL),
                m_pRefCount (NULL)
        {
        }

        // new object will point to a memory location on heap given by 'pObj'
        // Strong exception guarantee
        explicit SmartPtr (T *pObj)
            :   m_pT (pObj),
                m_pRefCount (NULL)
        {
            try
            {
                m_pRefCount = new int;
            }
            catch (...)
            {
                checkedDelete (m_pT);
                throw;
            }

            *m_pRefCount = 1;
        }

        // new object will refer to same memory on heap as 'rObj'
        // no-throw guarantee
        SmartPtr (const SmartPtr<T> &rObj)
            :   m_pT(rObj.m_pT), 
                m_pRefCount(rObj.m_pRefCount) 
        { 
            if (m_pRefCount != NULL)
                (*m_pRefCount)++;
        }


        // make 'rObj' and 'this' will refer to same object on heap
        // no-throw guarantee
        SmartPtr& operator= (const SmartPtr<T> &rObj)
        {
            // uses copy-and-swap idiom
            this_type(rObj).swap(*this);
            return *this;
        }

        // assign this smart pointer to another object on heap
        // Strong exception guarantee
        SmartPtr& operator= (T *pTObj)
        {
            // try and setup memory for reference counter
            int *pNewRefCount;
            try                             
            {
               pNewRefCount = new int;
            }
            catch (...)
            {
                delete pTObj;
                throw;
            }

            // stop referring to previous object
            updateCountAndTriggerDelete ();

            // start referring to new object
            m_pRefCount = pNewRefCount;
            *m_pRefCount = 1;

            m_pT = pTObj;

            return *this;
        }

        // no-throw guarantee
        ~SmartPtr ()
        {
            updateCountAndTriggerDelete ();
        }

        // returns true if this object is holding a reference
        // to an object on heap
        // no-throw guarantee
        bool isAssigned()
        {
            return !(m_pT == NULL);
        }

        // no-throw guarantee
        T* operator->()
        {
            return m_pT;
        }

        // no-throw guarantee
        T& operator*()
        {
            return *m_pT;
        }

    private:

        // make sure we dont delete a incomplete type pointer
        // no-throw guarantee
        template <class S>
        void checkedDelete (S* pSObj)
        {
            typedef char type_must_be_complete[ sizeof(S)? 1: -1 ];
            (void) sizeof(type_must_be_complete);
            delete pSObj;     
        }

        // count the references and delete it if this is last reference
        // no-throw guarantee
        void updateCountAndTriggerDelete ()
        {
            if (m_pRefCount != NULL)
            {                  
                (*m_pRefCount)--;

                // if this is last reference delete the memory
                if (*m_pRefCount == 0)
                {
                    checkedDelete (m_pRefCount);
                    checkedDelete (m_pT);
                }
            }
        }

        // swap the pointer values of 'rObj' with values of 'this'
        // no-throw guarantee
        void swap (SmartPtr<T> &rObj)
        {
            std::swap (m_pT, rObj.m_pT);
            std::swap (m_pRefCount, rObj.m_pRefCount);
        }

        // pointer to memory location of object
        T *m_pT;

        // pointer to memory location where 'reference' count of
        // object pointed to by m_pT is kept
        int *m_pRefCount;

        typedef SmartPtr<T> this_type;
};

} // namespace smartptrnamespace

#endif // SMARTPTR_HPP
EN

回答 2

Code Review用户

发布于 2013-04-18 21:40:24

一些非专家的评论:

  • 我更希望私人vars能排在第一位--以避免立即滚动到底部。
  • m_pRefCount成为指向int的指针而不是简单的int有什么好处吗?
  • 为什么需要使用checkedDelete来删除指向您自己创建的int的指针?如果您不使用checkedDelete作为本地int,那么函数可以采用模板类型T而不是新的类S。难道没有更好的方法来检查不完整类型吗?(表现出我的无知)有必要吗?
票数 1
EN

Code Review用户

发布于 2013-04-19 08:59:44

  1. API应该类似于现有共享指针的API,比如std::(tr1::)shared_ptr。他们有着广为人知的设计API,没有必要在没有充分理由的情况下发明新的东西。
  2. 指针应该有一个operator bool,而不是isAssigned,它应该是const。 In C++这将是explicit operator bool() const,在C++03 -安全-bool成语中.
  3. 那些试图抓住的拦网太糟糕了。您应该首先编写unique_ptr,并使用它暂时拥有对象:显式SmartPtr (T *pObj):m_pT(pObj),m_pRefCount() { unique_ptr temp(pObj);m_pRefCount = new (1);temp.release()};
  4. 赋值运算符可以通过值获取参数: void operator= (SmartPtr rObj) { swap(rObj);}
  5. 作为赋值操作符的复制器都应该是模板,以允许类似于struct派生的代码: Base {.};SmartPtr d=.;SmartPtr b= d;
  6. operator= (T *pTObj)应该使用SmartPtr (T *pObj) ctor和dtor void operator= (T *pTObj) { SmartPtr(pTObj).swap(*this);}
  7. SmartPtr<T>(NULL)坏了。
  8. 您可以编写typedef SmartPtr this_type; (没有<T>)
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/25214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档