Почему'т вектор::ясный удалить элементы из вектора?

Когда я использовать очистить() на СТД::вектор, предполагается уничтожить все элементы в "вектор", но вместо этого он не'т.

Пример кода:

vector<double> temp1(4);
cout << temp1.size() << std::endl;
temp1.clear();
cout << temp1.size() << std::endl;

temp1[2] = 343.5; // I should get segmentation fault here ....

cout << "Printing..... " << temp1[2] << endl;
cout << temp1.size() << std::endl;

Теперь, я должен был получить ошибку сегментации при попытке получить доступ к очищенной вектор, но вместо этого он заполняет в стоимость (что по мне очень глючит)

Результат выглядит следующим образом:

4
0
Printing..... 343.5
0

Это нормально? Это очень жесткий баг в месте, который в основном убил мой код в течение нескольких месяцев.

Комментарии к вопросу (6)

Ты не имеешь права сделать ошибку сегментации. Если на то пошло, ошибка сегментации это'т даже часть c++. Программы это удаление всех элементов из вектора, и вы'повторно незаконно доступа к контейнеру в аут. Это неопределенное поведение, а значит все может случиться. И действительно, что-то случилось.

Комментарии (2)
Решение

Когда вы получаете доступ вне границ вектор, вы получите неопределенное поведение. Это значит, что все может случиться. Ничего.

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

Если вы хотите, чтобы проверка границ, использовать на функцию-член () вместо оператора []`. Он будет бросать исключение вместо вызова неопределенное поведение.

Комментарии (0)

Из cppreference:

пустота очистить();

удаляет все элементы из контейнера. Делает недействительными все ссылки, указатели и итераторы, ссылаясь на содержащиеся элементы. Может привести к После-окончания итераторы. Многие реализации не освобождает выделенную память после вызова очистить(), фактически оставив емкость вектора неизменной.

Так что причин нет очевидной проблема в том, что вектор все-таки имеет памяти, доступной в магазине. Конечно, это лишь реализации, но не ошибка. Кроме того, как и другие ответы указывают, ваша программа имеет неопределенное поведение для доступа к очищенной содержание в первую очередь, так что технически все может случиться.

Комментарии (13)

Позвольте'ы представьте, что вы'вновь богатый (возможно, вы или вы не'т ... бы то ни было)!

Поскольку вы'вновь богатый вы покупаете кусок земли на Муреа (Наветренные острова, Французская Полинезия). Вы'вновь очень уверен, что это-хороший отель, так что вы построить виллу на этом острове и жить там. Ваш вилла имеет бассейн, теннисный корт, большой гараж и даже более приятные вещи.

Через некоторое время вы оставите Муреа, поскольку вы думаете, что это'ы становятся очень скучными. Много спорта, но мало кто. Вы продаете земельный участок и вилла и решили переехать куда-то еще.

Если вы вернетесь через некоторое время вы можете столкнуться с большим количеством разных вещей, но вы не можете быть уверены даже один из них.

  • Ваша вилла будет заменен на отель Club.
  • Ваша вилла может быть еще там.
  • Остров может быть впалыми.
  • ...

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

У вас нет никаких гарантий того, что вы'вновь гонг, чтобы обнаружить, если вы вернетесь и что's одинаково с вектором, который содержит три указатели в реализациях я'вэ посмотрел: (Имена могут быть разными, но функция в основном одинаковы.)

  • начало указывает на начало выделенной области памяти (т. е. х)
  • "конец", который указывает на конец выделенной памяти +1 (т. е. начать+4)
  • последний, который указывает на последний элемент в контейнере +1 (т. е. начать+4)

Позвонив очистить контейнер вполне может уничтожить всех элементов и сброс последний = начать;. Размер функции () скорее всего возвращение последнего-начать, - и поэтому вы&#39;МР соблюдать размер контейнера 0. Тем не менее,начало, все еще может быть в силе и все еще может быть выделено памяти ("конец" может все еще бытьначать+4`). Вы можете все еще наблюдать значения, которые вы поставили перед ясны().


std::vector a(4);
a[2] = 12;
cout 
Комментарии (1)

Оператор [] является эффективным, но имеет свою цену: он не выполняет проверку границ.

Есть более безопасные, но эффективный способ получить доступ к вектору, как итераторы и так далее.

Если вам нужен вектор для произвольного доступа (т. е. не всегда последовательно), либо быть очень осторожны, как вы пишете свои программы, или использовать менее эффективным на()`, который в тех же условиях будет иметь исключение.

Комментарии (2)

Если вы используете

temp1.at(2) = 343.5;

вместо

temp1[2] = 343.5;

вы хотели найти проблема. Рекомендуется использовать функцию В ()и оператор[]` не'т проверить границы. Вы можете избежать ошибок, не зная реализация вектора в STL.

Кстати, я запустить свой код в мой Убунту (12.04), получается так, что вы говорите. Однако, в с Win7, это's сообщило, что "утверждения" по.

Ну, это напоминает мне типа stringstream. Если определить наказание


stringstream str;
str 
Комментарии (1)

вы можете получить Сег вина, но это не точно, т. к. для доступа из элементов диапазона вектора оператор[]послеочистить()вызывается перед Это просто неопределенное поведение. Из вашего поста похоже, что вы хотите попробовать, если элементы будут уничтожены, так что вы можете использоватьв` публичную функцию для этого:

функция автоматически проверяет, является ли N-это в пределах допустимые элементы в векторе, бросив out_of_range исключение, если это > есть не (т. е., если n больше или равно, чем его размер). Это В отличие от оператора-членов[], это не проверка границ.

кроме того, после очистить():

Все итераторы, указатели и ссылки, связанные с этим контейнером, признан недействительным.

http://www.cplusplus.com/reference/vector/vector/at/

Комментарии (0)

попробуйте получить доступ к элементам вечерять, чем 4 что вы используете для конструктора может быть вы получите ошибку сегментации Другая идея cplusplus.com:

Очистить содержимое

Удаляет все элементы из вектора (которые разрушаются), оставив контейнер с размером 0.

Перераспределение не гарантированно произойдет, а вектор мощностей не гарантированные изменения в связи с вызовом этой функции. Типичная альтернатива, которая заставляет перераспределения является использование свопа:

вектор в<Т>().своп(х); // удалить X перераспределения

Комментарии (0)

Да это нормально. ясно()не&#39;т гарантировать перераспределение. Попробуйте использовать размер() после очистить().

Комментарии (1)

в одно важное дополнение к до сих пор ответы: если класс вектор instanciated обеспечивает деструктор, то он будет вызван на поляне (и на размер(0)`, тоже).

Попробуйте это:

struct C
{
    char* data;
    C()           { data = strdup("hello"); }
    C(C const& c) { data = strdup(c.data); }
    ~C()          { delete data; data = 0; };
};
int main(int argc, char** argv)
{
    std::vector v;
    v.push_back(C());
    puts(v[0].data);
    v.clear();
    char* data = v[0].data; // likely to survive
    puts(data);             // likely to crash
    return 0;
}

Эта программа скорее всего вылетит с ошибкой сегментации, но (очень вероятно) не на типа char* данные = в[0].данных;, но ставит строка(данные);` (использовать отладчик, чтобы увидеть).

Типичный вектор реализаций оставить память, выделенная нетронутыми и оставить все как есть только после вызова деструкторов (впрочем, не факт - помню, это неопределенное поведение!). Последнее, что было сделано, было установление данных с экземпляром на nullptr, и хотя не действует в смысле языка C++/вектор, память еще есть, так что доступ к нему (незаконно) без сегментации. Это происходит, когда разыменования `типа char* указатель на данные в ставит, как null...

Комментарии (0)