我以前从未使用过std::shared_ptr,我也不知道这个智能指针实际上是如何工作的,但我决定创建一个来验证我的知识。这是我的代码:
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;
};
}我遗漏了什么?我实现了这个智能指针对吗?如能提出建议,将不胜感激。
发布于 2016-09-07 14:33:41
我遗漏了什么?
几件事。
std::nullptr_t类型的对象。shared_ptr<U>类型的对象,其中U是从T派生的。当然还有更多。在聪明的指针中,你总是忘记一些东西。
我实现了这个智能指针对吗?
YOu实现了三条规则。所以除非有虫子,否则应该是好的。
如能提出建议,将不胜感激。
我在文章中详细介绍了以下内容:
唯一指针
智能指针
建设者
在this->代码中看到C++并不是很正常(与C++不同)。
实际上,我认为使用this->是不好的做法。您只需要在本地/参数和成员名称之间存在一些模糊性时才使用this->member。
如果您有一些歧义,那么您在命名方面做得很差,并且您正在使用this->来掩盖这个问题。更愿意解决这个问题,因为由于你的懒惰,一些糟糕的维护人员稍后会出现并使用错误的变量。
我通常打开编译器警告,它告诉我的局部变量是否正在跟踪另一个变量,从而迫使我有唯一(和有意义的名称)。
shared_ptr(const shared_ptr &p) : refCount(nullptr), t(nullptr)对我来说,这看起来就像多个任务打包在同一条线上。
varOne = 5; varTwo = 6; theOtherOne = doStuff(5);我认为大家都同意一句话应该是一句话。为什么不将此应用于您的参数列表。它将使读取代码更加容易,同时也会验证初始化问题的顺序。
shared_ptr(const shared_ptr &p)
: refCount(nullptr)
, t(nullptr)
{
/* Stuff */
}具有空ptr的
nullptr构建,会发生什么?
X* ptr = nullptr; shared_ptr<X> data1(ptr); shared_ptr<X> data2(nullptr); // should have its own constructor.isvalid()的双重检查是浪费如果p.isvalid()为真,则在复制后isvalid()为真。
shared_ptr(const shared_ptr &p) : refCount(nullptr), t(nullptr)
{
if(p.isvalid())
{
refCount = p.refCount;
t = p.t;
if(isvalid())
(*this->refCount)++;
}
}而且,这也可以简化得多。
shared_ptr(const shared_ptr &p)
: refCount(p.refCount)
, t(p.t)
{
if(isvalid()) {
(*refCount)++;
}
} 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);
}对不起,这个功能很大,很笨拙,很难读懂。它也没有提供强有力的例外保证。在更新该对象的内容之前,您可以修改该对象的内容,进行异常、危险的工作(调用破坏)。
要以异常安全的方式执行任何工作,您需要遵循三个步骤的流程。
这三个步骤的过程是由复制和交换成语。
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;
}很多人把这一步向前走了一步。并在参数中进行复制:
shared_ptr& operator =(shared_ptr p) // Notice the pass by value.
{ // this gets your copy.
p.swap(*this);
return *this;
}这两个函数不会改变对象的状态。
T* operator ->() {return t;}
T& operator *() {return *t;}因此,它们可能应该被标记为const。
发布于 2016-09-07 07:28:40
https://codereview.stackexchange.com/questions/140693
复制相似问题