16

当应用于向量时,我在理解 C++ clear 函数的行为时遇到了一些困难。

我尝试编译并运行以下函数:

#include <iostream>
#include <vector>
using namespace std;

int main ()
{
  unsigned int i;
  vector<int> myvector;
  myvector.push_back (1);
  myvector.push_back (2);
  myvector.push_back (3);

  cout << "myvector contains:";
  for (i=0; i<myvector.size(); i++) cout << " " << myvector[i];

  myvector.clear();
  myvector.push_back (11);
  myvector.push_back (12);

  cout << "\nmyvector contains:";
  for (i=0; i<myvector.size(); i++) cout << " " << myvector[i];
  cout << endl;

  cout << " entry3 = " << myvector[2]<<endl;

  return 0;
}

这是输出:

myvector contains: 1 2 3
myvector contains: 11 12
entry3 = 3

怎么可能在清空vector的时候,vector的第三个entry的信息还没有被擦除呢?

4

2 回答 2

24

从文档:

删除向量的所有元素:调用它们的析构函数,然后将它们从向量容器中删除,使容器的大小为 0。

基本上,您正在调用未定义的行为myvector[2]因为该项目不再存在。调用后,您只在向量中推送了 2 个元素clear(),因此只有索引01可访问。

你很不幸它没有崩溃,因为看起来工作可以隐藏错误。无法保证该值已被删除。

尝试使用.at(2)而不是访问元素将导致抛出异常(operator[]()不进行任何边界检查,而at()确实如此)。

于 2012-10-11T13:33:00.797 回答
7

如果您尝试在debug模式下运行此代码,它很可能会因调试断言而崩溃。超过数组末尾的引用是未定义的行为

实际发生的是 vector 在你运行之前没有擦除它之前使用的内存clear()。该内存仍然存在,但尚未定义如果您访问它会发生什么。您可以执行边界检查以避免超出向量的末端。您可以通过循环size()作为边界或通过使用at()和捕获out_of_range异常来做到这一点。我不会特别推荐后一种方法,因为将异常用于运行时检查并不是一个好主意。

于 2012-10-11T13:34:19.363 回答