在休假的赋值运算符中,我将删除我所在的类的动态分配的数据成员。在上交代码时,我不小心将“删除”留在了其中,但它似乎仍然可以正常工作。当我调用delete时到底发生了什么?如果我在将m_itemArray分配给Swap函数中的temp之前删除m_itemArray,那么swap函数仍如何工作?
分配运算符:
Set& Set::operator=(const Set& rhs)
{
if (this != &rhs)
{
delete[] m_itemArray;
Set temp(rhs);
swap(temp);
}
return *this;
}
交换功能:
void Set::swap(Set& other)
{
ItemType * temp = m_itemArray;
m_itemArray = other.m_itemArray;
other.m_itemArray = temp;
}
我认为它现在可以正常工作的方式是让计算机访问m_itemArray正在使用的内存,但是我很幸运,因为计算机到那时还没有编辑存储在该内存空间中的任何内容我正在访问交换功能。
答案 0 :(得分:1)
严格来说,删除它什么都没有;它不再拥有,但直到有其他东西写入它为止,值仍将存在(对于大多数分配器)。但是,尝试访问未分配的内存是未定义的行为,任何事情都可能发生。
我打电话给delete时到底发生了什么
内存被释放回管理器。
如果我要在交换功能中将m_itemArray分配给temp之前删除m_itemArray,交换功能如何仍然起作用?
它只是碰巧还在那儿。该行为是不确定的。
答案 1 :(得分:1)
您的假设几乎可以肯定是正确的。除了在非常高安全性的系统中或使用调试工具时,没有理由重写已释放的内存(删除操作会发生这种情况)。
实际上,甚至释放本身也可能不会立即发生,而是在更方便的时间执行(此操作可能会变得越来越复杂,并成为所谓的垃圾收集器,而垃圾收集器又会导致使用显式发布是不必要的-但主题变得复杂)。
因此,直到那一刻,该内存仍然可以访问并且可以使用。即使在此之后,该值也有可能不会被重用和覆盖,并且仍然可行(这可能有助于隐藏实际上是危险的bug)。当然,您无法保证,尝试访问释放的内存可能会导致各种麻烦。
要捕获此类错误,在某些系统中,您可以将可执行文件与其他内存管理器或库进行链接,这些库或库将在实际释放内存之前,使用随机或告诉值覆盖即将发布的内存。对于没有真正硬件保护支持的较旧系统,例如MS-DOS,这是唯一可能的检查,并且在相当长的一段时间内它仍然是一个受欢迎的选择(例如,我记得electricfence)。