2015-04-09 4 views
2

Почему с помощью vector.erase(vector.end()) производитСтирание vector.end() не

Segmentation fault (core dumped) 

при использовании этого кода:

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

void printMe(vector<int>& v){ for(auto &i:v) cout<<i<<" "; cout<<"\n"; } 

int main() { 
    vector<int> c = { 1,2,3,4,5,6,7,8}; 
    printMe(c); 
    c.erase(c.begin()); 
    printMe(c); 
    c.erase(c.begin()); 
    printMe(c); 
    // c.erase(c.end()); //will produce segmentation fault 
    // printMe(c); 
    return 0; 
} 

Я немного нового в этих итераторов, так что поймал меня охранник. Хотя я знаю, существует vector.pop_back(). Мне любопытно узнать, что именно вызывает это.

A link к программе.

+4

'vector.end()' - это итератор прошедшего конца. Он не указывает на элемент, который можно стереть. –

+0

@ T.C. теперь мне любопытно, почему .end() указывает на прошлые, любые варианты использования? потому что конец обычно ссылается на последний элемент, поскольку я получаю от begin-> указание на 1-й элемент. –

+5

http://stackoverflow.com/questions/9963401/why-are-standard-iterator-ranges-begin-end-instead-of-begin-end – user657267

ответ

3

vector::end() не указывает на последний элемент, он указывает на элемент сразу после последний элемент.

Цитирование cplusplus.com,

std::vector::end

Возвращает итератор со ссылкой на пришедшую к конечному элементу в векторе контейнере.

Промежуточный элемент - это теоретический элемент, который будет следовать за последним элементом вектора: . Он не указывает на какой-либо элемент, и поэтому не может быть разыменован.

Поскольку диапазоны, используемые функций стандартной библиотеки не включать элемент, на который указывает их закрытия итератора, эта функция часто используется в комбинации с vector::begin, чтобы определить диапазон включая все элементы в контейнере.

Следовательно, он не имеет ничего общего с erase() и, следовательно, является ошибкой.


Заменить

c.erase(c.end()); 

с

c.erase(c.end() - 1); 
+0

Не существует перегрузки 'erase', которая принимает' reverse_iterator'. 'std :: reverse_iterator' позволяет вам восстановить базовый итератор с' .base() ', но' rbegin(). base() 'просто' end() ', поэтому мы вернулись туда, где мы начали. –

+0

@ T.C. Вы правы, я удалил часть «reverse_iterator». Поскольку нам все равно придется использовать '.base()' для преобразования обратного итератора для пересылки итератора, который не имеет продуктивного использования. – shauryachats

0

vector::end() указывает на один после последнего элемента.

Поэтому он не указывает на элемент.

Таким образом, ничего не нужно удалять.

Если вы хотите удалить последний элемент, вам нужно удалить элемент до этого, как в вашей идеонной ссылке.

0

Вектор end() возвращает итератор, ссылающийся на элемент, который должен быть ПОСЛЕ последнего элемента в контейнере.

Итак, вы пытаетесь стереть память, которая не принадлежит вам, это создает SIGSEGV (11).

0

Как упоминалось выше volerag просто заменить c.erase (с.конец()); с c.erase (c.end() - 1);

Смежные вопросы