gpt4 book ai didi

c++ - 试图找出何时调用析构函数

转载 作者:行者123 更新时间:2023-11-30 04:10:53 24 4
gpt4 key购买 nike

下面我有一个保存引用计数的类和一个封装指向另一个对象的指针的类。

Ptr 类不再有任何对象附加到它时,我想解除分配。这需要删除对象和引用计数。当 ptrcnt 的值达到零时发出信号。

我的 Ptr_count 类有一个析构函数,它负责解除分配。我知道当 Ptr 的析构函数被调用时,这个析构函数将被调用,并且它会相应地释放内存。但是,我不太确定当 Ptr 的赋值运算符被调用时它会被调用并且代码 if(--refptr == 0) { delete p; } 被执行。

Ptr_count中有一段代码被注释掉了。如果我使用它而不是析构函数,则只要 refptr 的值变为零,就会发生释放。

我的问题是,在 Ptr 中的赋值操作期间是否可以调用析构函数,或者我是否需要使用 Ptr_count 中注释的代码out 以获得正确的内存释放?

显然,当我退出程序时,析构函数将被调用,内存将以一种或另一种方式释放,但在程序运行时,我认为在这种情况下,引用指针即使在达到零后也可以继续递减并且那段内存仍然存在。

class Ptr_count {
public:
Ptr_count() : ptrcnt(new size_t(1)) { }
~Ptr_count()
{
if(ptrcnt && *ptrcnt <= 0)
delete ptrcnt;
}
size_t operator++() const
{
++(*ptrcnt);
return *ptrcnt;
}
size_t operator--() const
{
--(*ptrcnt);
/*
if(*ptrcnt == 0) {
delete ptrcnt;
return 0;
}
*/
if(ptrcnt)
return *ptrcnt;
else
return 0;

}
operator bool() const
{
return ptrcnt;
}
size_t operator*() const
{
return *ptrcnt;
}
private:
size_t* ptrcnt;
};

template <class T> class Ptr {
public:
Ptr() : p(0) {}
Ptr(T* t) : p(t) {}
Ptr(const Ptr& h) : p(h.p), refptr(h.refptr) { ++refptr; }

Ptr& operator=(const Ptr& rhs)
{
++(rhs.refptr);
if(--refptr == 0) {
delete p;
}
refptr = rhs.refptr;
p = rhs.p;
return *this;
}

~Ptr()
{
if(--refptr == 0) {
delete p;
}
}

operator bool() const { return p; }

private:
T* p;
Ptr_count refptr;
};

编辑::

或者,如果 Ptr_count 类有它自己的赋值运算符,这是否可以解决该问题?如果我将以下代码添加到 Ptr_count,似乎我可以在分配期间引用计数达到 0 时释放内存。

void operator=(const Ptr_count& rhs)
{
if(ptrcnt == 0)
delete ptrcnt;
ptrcnt = rhs.ptrcnt;
}

最佳答案

首先,如果这是为了自学,那就继续吧。否则停止你正在做的事情并开始使用 std::shared_ptr/std::unique_ptr/std::weak_ptr或者如果你不能使用 C++11 std::auto_ptr .

现在你的代码:

1) 在复制构造函数 Ptr_count 而不是 Ptr 的复制构造函数中增加引用计数会更安全、更自然>,因为 Ptr_count 类的目的是管理引用计数。

这样做之后,您可以完全删除 Ptr 的复制构造函数。

2)Ptr的赋值运算符中存在不必要的检查:

// Counter *must* be greater than 0 here, else p is 0 anyways.
Ptr& Ptr::operator=(const Ptr& rhs)
{
++(rhs.refptr); // Increment your counter to 2 or above.
if(--refptr == 0) { // Decrement your counter to 1 or above.
delete p; // Never get here.
}
refptr = rhs.refptr;
p = rhs.p;
return *this;
}

3) 您最大的问题是您在赋值运算符中覆盖了 refptrp

Ptr& operator=(Ptr const& rhs)
{
Ptr temp(rhs);
std::swap(refptr, temp.refptr);
std::swap(p, temp.p);
return *this;
}

应该解决这个问题。

4) Ptr_count 的递减运算符有些问题。

size_t Ptr_count::operator--() const
{
--(*ptrcnt); // Access address stored in ptrcnt.
if(ptrcnt) // Test if address is valid.
return *ptrcnt;
else
return 0;

}

如果在调用此方法时 ptrcnt 为 0,则会因为 --(*ptrcnt) 而发生访问冲突。无论如何,这应该不是必需的,只需将其删除:

size_t Ptr_count::operator--() const
{
return --(*ptrcnt);
}

长话短说因为代码说了1000多字,完整代码:

class Ptr_count {
public:
Ptr_count() : ptrcnt(new size_t(1)) { }
Ptr_count(Ptr_count const& rhs) : ptrcnt(rhs.ptrcnt) { ++(*this); }
~Ptr_count()
{
if(ptrcnt && *ptrcnt <= 0)
delete ptrcnt;
}
size_t operator++()
{
return ++(*ptrcnt);
}
size_t operator--()
{
return --(*ptrcnt);

}
operator bool() const
{
return ptrcnt;
}
size_t operator*() const
{
return *ptrcnt;
}
private:
size_t* ptrcnt;
};

template <class T> class Ptr {
public:
Ptr() : p(0) {}
Ptr(T* t) : p(t) {}

Ptr& operator=(Ptr const& rhs)
{
Ptr temp(rhs);
std::swap(refptr, temp.refptr);
std::swap(p, temp.p);
return *this;
}

~Ptr()
{
if(--refptr == 0)
delete p;
}

operator bool() const { return p; }

private:
T* p;
Ptr_count refptr;
};

关于c++ - 试图找出何时调用析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20413370/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com