c++ - 删除对象时调试断言失败

标签 c++ object vector delete-operator erase

我最近遇到了一些我用 C++ 编写的代码的问题,我无法找到解决方案。这个问题乍一看似乎很简单,但由于某种原因程序抛出错误,我无法解释原因。 我不会复制粘贴我遇到错误的原始代码(因为它太麻烦了),但这是它的简化版本,它在相同的上下文中表现出完全相同的行为:

#include<vector>
using namespace std;
class A_class
{
  bool *heap_space;    //can be any type of pointer
public:
  A_class()  { heap_space = new bool[4]; }
  A_class(const A_class&)  { heap_space = new bool[4]; }
  ~A_class()  { delete[] heap_space; }
};
void main()
{
  vector<A_class> ObjArr(5);
  vector<A_class>::iterator iTer = ObjArr.begin() + x; 
  //where x can be any number from 0 to 3
  ObjArr.erase(iTer);
}

我知道代码看起来简单得不切实际,但我似乎无法找出引发异常的原因。该代码将抛出“调试断言失败!”每次我尝试运行它时,都会在运行时显示“表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)”消息。

提及该消息在容器的删除方法期间不会立即出现可能也很有用。它仅在 vector 超出范围后出现。 因此,我一直尝试通过各种方法修复错误,方法是在 vector ​​超出范围之前添加代码(例如在删除后立即重新插入新元素)但没有成功。此外,经过一些试验后,我发现该消息仅在删除 vector 的最后一个元素 (ObjArr.end()-1) 以外的任何内容后才会出现。如果 vector 的最后一个元素被删除,显然没有什么不好的事情发生。希望这些提示有所帮助。 如果有人知道为什么会发生这种情况,请向我解释。我敢肯定我只是犯了一个新手错误,因为这似乎很容易弄清楚,但我做不到。

以上代码是在 Windows 7 下使用 Visual Studio 2013 编译的。

最佳答案

有趣的是,这是因为您没有提供赋值运算符。为什么需要一个?好吧,让我们考虑一个 vector 。 vector 对象有一个指向 5 个 A_class 数组的指针。它们是默认构造的,这没有问题,因为您已经定义了它。现在我们删除:

A_class }
A_class }
A_class }-- Erase one of these
A_class }
A_class }

有趣的是,如果我们删除最后一个,我们不会发现问题,只有当我们删除索引 0 到 3 中的一个时才会出现问题。为什么?好吧,当我们删除索引 2 时,我们得到他的:

A_class
A_class
-- empty space with size = sizeof(A_class)
A_class
A_class

为了协调这个空间,在删除结束时,std::vector 使用赋值运算符来修复数组。所以 index[2] = index[3]index[3] = index[4]。现在,因为您没有声明赋值运算符,它将使用默认值,包括 index[4] 的删除。这很糟糕,因为 index[4] 会给 index[3] 它的指针然后删除它,结果是这样的:

A_class // heap_space okay
A_class // heap_space okay
A_class // heap_space okay
A_class // heap_space deleted! will error when deconstructed

所以现在当我们退出时,我们试图删除 index[3],然后一切都崩溃了!

通过添加一个使用 swap 的赋值运算符,我们可以解决这个问题:

class A_class
{
public:
//...
    // note the byval argument
    A_class& operator=(A_class other) {
        std::swap(this->heap_space, other.heap_space);
        return *this;
    }
//...
}

关于c++ - 删除对象时调试断言失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20337804/

相关文章:

c++ - 从 map 访问,将字符串转换为 char*

c++ - 他们是否将 copy_if 添加到 c++0x?

javascript - 添加属性,打印对象时不会显示该属性

api - TensorFlow 对象检测 API - 对象检测 API 中的损失意味着什么?

c++ - 从一个类到另一个类直接访问存储在 vector 中的数据

c++ - 需要对条件变量寻求的互斥保护(原子)赋值吗?

c++ - 模板化优先级队列继承自模板化堆

c++ - 尝试创建 SceneNode 时分配抽象类类型的对象

c++ - Graham Scan C++无法正常工作

c++ - vector 中结构的类型名称是什么