Почему std :: vector :: erase не перегружен, чтобы принимать целочисленные индексы?

std::vector::erase примет либо один итератор, обозначающий позицию удаляемого элемента, либо два итератора, обозначающие диапазон. Но вы не можете сделать это:

std::vector<int> vec = { 1, 2, 3 };
vec.erase(1);

Скорее вы должны сделать что-то вроде

vec.erase( vec.begin()+1 );

Это кажется ненужной дополнительной работой — просто интересно, есть ли какая-то причина из POV дизайна класса, почему эта перегрузка не будет включена?

редактировать: Выбрал наиболее полный ответ, все были хорошими. Также, когда я пишу это, у этого поста есть 4 близких голоса за то, что он «не конструктивен»; однако, учитывая качество ответов, я думаю, что это был явно полезный вопрос, безусловно, для меня.

2

Решение

Есть две причины, которые я могу придумать:

1) erase является общей функцией-членом для контейнеров. Использование индексов имеет смысл только для некоторых контейнеров, поэтому при использовании итераторов вам не нужно беспокоиться о типе контейнера, с которым вы работаете. Например, индексы имеют смысл только для контейнеров с произвольным доступом, используя итераторы, вы повышаете гибкость своего кода и т. Д.

2) erase хорошо работает со стандартными алгоритмами, такими как std::remove, std::remove_if, std::uniqueи т. д. Чаще встречается желание стереть элементы на основе некоторого предиката и т. д., а не жестко кодировать индексный номер. Ищите «стереть-удалить идиому» для получения дополнительной информации.

По сути, итераторы считаются превосходящими индексирование по многим причинам, и это то, что вы увидите, широко используется в стандартной библиотеке C ++. Индексы лучше использовать для симулированного доступа к массиву, если это имеет смысл.

1

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

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

2

Представь, если бы ты

typedef std::set<int> MyContainer
MyContainer c;
// ...
c.erase(5);  // Or a programmatic int

Теперь, если вы измените базовый контейнер MyContainer (путем обновления typedef) чтобы vector вдруг ваш erase полностью изменился в смысловом значении и до сих пор компилируется! Я не могу представить ни одного другого случая, когда такое простое изменение типа контейнера привело бы к такому другому поведению.

Чтобы избежать этого, erase имеет только входные значения или итераторы, но не индекс.

2
По вопросам рекламы [email protected]