标题几乎说明了一切,我几乎肯定它在复制构造函数或赋值运算符中,我很确定它是后者。这是一个非常短的课程,所以我会发布整个事情,任何关于如何处理它的建议都会很好。老实说我在这里也有点过头了,所以任何指向一些可靠阅读的人都会非常感激。
#pragma once
//for non-learning purposes, boost has a good smart pointer
template <class type>
class sPtr
{
private:
type *p;
int r; //referenceCount
void add()
{
r++;
}
int release()
{
return --r;
}
public:
sPtr(): p(NULL), r(1) {}
sPtr(type *pValue): p(pValue)
{
add();
}
sPtr(const sPtr<type> & sp): p(sp.p), r(sp.r)
{
add();
}
~sPtr()
{
if(release() == 0)
{
delete p;
}
}
type* get()
{
return p;
}
type& operator*()
{
return *p;
}
type* operator->()
{
return p;
}
sPtr<type>& operator=(sPtr<type> sp)
{
std::swap(this->p, sp.p);
std::swap(this->r, sp.r);
add();
return *this;
}
};
我很确定赋值运算符应该通过引用传递,但我不确定这将如何影响实现。我尝试了一些不同的实现,但所有这些实现仍然存在漏洞。
答案 0 :(得分:5)
每个共享指针都会跟踪其自己的单独引用计数。这显然不好。当一个被销毁时,其他人的引用计数不会更新。您需要将引用计数保留在所有共享指针都可以访问的单独位置。
答案 1 :(得分:2)
除了Ben已经提到过的内容之外,您在默认构造函数中开始引用计数为1(而不是在其他构造函数中初始化它)。如果在默认构造函数之后为其指定指针,则引用计数为2,当您调用release时,返回1.简而言之,引用计数为0(表示可以删除对象)的唯一时间是如果你调用第1版比调用add更多的时间。通常,您希望这些调用是对称的(调用add对应于调用release)。