Вектор:: 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

Как возможно, что информация третьей записи вектора не была удалена при очистке вектора?

Ответы

Ответ 1

Из документов:

Все элементы вектора отбрасываются: их деструкторы вызываются, а затем они удаляются из векторного контейнера, оставляя контейнер размером 0.

В основном вы вызываете undefined поведение на myvector[2], потому что этот элемент больше не существует. Вы только нажали 2 элемента в векторе после вызова clear(), поэтому доступны только индексы 0 и 1.

Вам не повезло, что он не сработал, потому что работа на скрыть может скрыть ошибки. Там нет гарантии, что значение будет стерто.

При попытке получить доступ к элементу с помощью .at(2) будет выведено исключение (operator[]() не выполняет проверку границ, тогда как at() делает).

Ответ 2

Если вы попытаетесь запустить этот код в режиме debug, вероятно, он сработает с утверждением отладки. Ссылка на конец массива - undefined поведение.

Что на самом деле происходит, так это то, что вектор не уничтожил память, которую он ранее использовал, прежде чем вы запустили clear(). Эта память все еще присутствует, но она не определила, что произойдет, если вы ее получите. Это зависит от вас, чтобы выполнить проверку границ, чтобы избежать истечения конца вектора. Вы можете сделать это, выполнив цикл с помощью size() в качестве границ или используя at() и поймав исключение out_of_range. Я бы не особо рекомендовал этот последний подход, так как не рекомендуется использовать исключения для проверок времени выполнения.