首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >shared_ptr代码实现

shared_ptr代码实现
EN

Code Review用户
提问于 2016-09-07 02:25:20
回答 2查看 8.4K关注 0票数 5

我以前从未使用过std::shared_ptr,我也不知道这个智能指针实际上是如何工作的,但我决定创建一个来验证我的知识。这是我的代码:

代码语言:javascript
复制
namespace myStd
{
    template<class T>
    class shared_ptr
    {
        public : 

        shared_ptr() : refCount(nullptr), t(nullptr) {}
        shared_ptr(T *p) : refCount(new int(1)), t(p) {}

        ~shared_ptr()
        {
            this->destroy();
        }

        shared_ptr(const shared_ptr &p) : refCount(nullptr), t(nullptr)
        {
            if(p.isvalid())
            {
                refCount = p.refCount;
                t = p.t;

                if(isvalid())
                (*this->refCount)++;
            }
        }

        void destroy()
        {
            if(isvalid())
            {
                --(*refCount);
                if((*refCount) <= 0)
                {
                    delete refCount;
                    delete t;
                }

                refCount = nullptr;
                t = nullptr;
            }   
        }

        shared_ptr& operator =(const shared_ptr &p)
        {
            if(this != &p)
            {
                if(!p.isvalid())
                {
                    this->destroy();
                    this->refCount = p.refCount;
                    this->t = p.t;

                    if(isvalid())
                    (*this->refCount)++;

                    return (*this);
                }

                if(!isvalid())
                {
                    this->refCount = p.refCount;
                    this->t = p.t;

                    if(isvalid())
                    (*this->refCount)++;

                    return (*this);
                }
                else
                {
                    this->destroy();
                    this->refCount = p.refCount;
                    this->t = p.t;

                    if(isvalid())
                    (*this->refCount)++;                    
                }
            }
            return (*this);
        }

        bool isvalid() const {return (t != nullptr && refCount != nullptr);}
        int getCount() const {if(refCount != nullptr) return (*refCount); else return 0;}

        T* operator ->() {return t;}
        T& operator *() {return *t;}

        private : 
        int *refCount;
        T *t;
    };
}

我遗漏了什么?我实现了这个智能指针对吗?如能提出建议,将不胜感激。

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-09-07 14:33:41

我遗漏了什么?

几件事。

  • 构造函数,它接受std::nullptr_t类型的对象。
  • 构造函数,它接受shared_ptr<U>类型的对象,其中U是从T派生的。
  • 布尔转换运算符
  • 交换算子
  • 移动语义

当然还有更多。在聪明的指针中,你总是忘记一些东西。

我实现了这个智能指针对吗?

YOu实现了三条规则。所以除非有虫子,否则应该是好的。

如能提出建议,将不胜感激。

我在文章中详细介绍了以下内容:

唯一指针

智能指针

建设者

不要用这个。

this->代码中看到C++并不是很正常(与C++不同)。

实际上,我认为使用this->是不好的做法。您只需要在本地/参数和成员名称之间存在一些模糊性时才使用this->member

如果您有一些歧义,那么您在命名方面做得很差,并且您正在使用this->来掩盖这个问题。更愿意解决这个问题,因为由于你的懒惰,一些糟糕的维护人员稍后会出现并使用错误的变量。

我通常打开编译器警告,它告诉我的局部变量是否正在跟踪另一个变量,从而迫使我有唯一(和有意义的名称)。

一行语句

代码语言:javascript
复制
shared_ptr(const shared_ptr &p) : refCount(nullptr), t(nullptr)

对我来说,这看起来就像多个任务打包在同一条线上。

代码语言:javascript
复制
varOne = 5; varTwo = 6; theOtherOne = doStuff(5);

我认为大家都同意一句话应该是一句话。为什么不将此应用于您的参数列表。它将使读取代码更加容易,同时也会验证初始化问题的顺序。

代码语言:javascript
复制
shared_ptr(const shared_ptr &p)
    : refCount(nullptr)
    , t(nullptr)
{
    /* Stuff */
}

具有空ptr的

构造 shared_ptr(T *p) : refCount(new int(1)), t(p) {} 如果我用nullptr构建,会发生什么? X* ptr = nullptr; shared_ptr<X> data1(ptr); shared_ptr<X> data2(nullptr); // should have its own constructor.

isvalid()的双重检查是浪费

如果p.isvalid()为真,则在复制后isvalid()为真。

代码语言:javascript
复制
    shared_ptr(const shared_ptr &p) : refCount(nullptr), t(nullptr)
    {
        if(p.isvalid())
        {
            refCount = p.refCount;
            t = p.t;

            if(isvalid())
            (*this->refCount)++;
        }
    }

而且,这也可以简化得多。

代码语言:javascript
复制
    shared_ptr(const shared_ptr &p)
        : refCount(p.refCount)
        , t(p.t)
    {
        if(isvalid()) {
            (*refCount)++;
        }
    }

更喜欢在赋值时使用复制/交换成语.

代码语言:javascript
复制
    shared_ptr& operator =(const shared_ptr &p)
    {
        if(this != &p)
        {
            /* This LOOKS LIKE A BUG */
            /* Don't think the ! should be there. */
            if(!p.isvalid())
            {
                this->destroy();
                this->refCount = p.refCount;
                this->t = p.t;

                if(isvalid())
                (*this->refCount)++;

                return (*this);
            }

            if(!isvalid())
            {
                this->refCount = p.refCount;
                this->t = p.t;

                if(isvalid())
                (*this->refCount)++;

                return (*this);
            }
            else
            {
                this->destroy();
                this->refCount = p.refCount;
                this->t = p.t;

                if(isvalid())
                (*this->refCount)++;                    
            }
        }
        return (*this);
    }

对不起,这个功能很大,很笨拙,很难读懂。它也没有提供强有力的例外保证。在更新该对象的内容之前,您可以修改该对象的内容,进行异常、危险的工作(调用破坏)。

要以异常安全的方式执行任何工作,您需要遵循三个步骤的流程。

  1. 把一份复制成临时的。异常情况下的->是可以飞行的。
  2. 调换温度和电流。->安全作为交换不应引发异常。
  3. 摧毁然后是临时工。->安全,因为现在的状态是好的。

这三个步骤的过程是由复制和交换成语。

代码语言:javascript
复制
 shared_ptr& operator =(const shared_ptr &p)
 {
     shared_ptr  temp(p);    // Constructor copies. Destructor destoryes.
     temp.swap(*this);       // Perform an exception safe transfer of state.
     return *this;
 }

很多人把这一步向前走了一步。并在参数中进行复制:

代码语言:javascript
复制
 shared_ptr& operator =(shared_ptr p)  // Notice the pass by value.
 {                                     // this gets your copy.
     p.swap(*this);
     return *this;
 }

Const正确性

这两个函数不会改变对象的状态。

代码语言:javascript
复制
    T* operator ->() {return t;}
    T& operator *() {return *t;}

因此,它们可能应该被标记为const

票数 7
EN

Code Review用户

发布于 2016-09-07 07:28:40

  • operator=()方法有四条返回语句。我更喜欢这个== &p的单一的,或者可能是另一个早期的回报。
  • 操作符中的代码复制=。
  • 不需要破坏方法,IMO。
  • getCount()应该调用isValid。
  • isValid只需检查指针。refcount != nullptr当且仅当指针!= nullptr。
  • 复制构造函数不需要检查这个->isvalid(),对吗?在operator=中同样的事情
  • 在refCount()中断言( >= 0)。
  • 更多的断言()会更好,例如在操作符->和*中。
票数 -1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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