vector :: clear в стеке переполнения

У меня есть некоторые трудности в понимании поведения функции очистки C ++ применительно к вектору.

Я попытался скомпилировать и запустить следующую функцию:

#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

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

15

Решение

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

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

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

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

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

22

Другие решения

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

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

7