Инкрементные указатели - это идиоматический C ++, потому что семантика указателей отражает фундаментальный аспект философии проектирования, лежащей в основе стандартной библиотеки C ++ (на основе STL Александра Степанова )
Важной концепцией здесь является то, что STL разработан вокруг контейнеров, алгоритмов и итераторов. Указатели - это просто итераторы .
Конечно, способность увеличивать (или добавлять / вычитать) указатели восходит к C. Многие алгоритмы манипуляции с C-строками могут быть написаны просто с использованием арифметики указателей. Рассмотрим следующий код:
char string1[4] = "abc";
char string2[4];
char* src = string1;
char* dest = string2;
while ((*dest++ = *src++));
Этот код использует арифметику указателей для копирования C-строки с нулевым символом в конце. Цикл автоматически завершается, когда встречается с нулем.
В C ++ семантика указателей обобщается на концепцию итераторов . Большинство стандартных контейнеров C ++ предоставляют итераторы, к которым можно получить доступ через функции-члены begin
и end
. Итераторы ведут себя как указатели в том смысле, что их можно увеличивать, разыменовывать, а иногда уменьшать или расширять.
Чтобы перебрать std::string
, мы бы сказали:
std::string s = "abcdef";
std::string::iterator it = s.begin();
for (; it != s.end(); ++it) std::cout << *it;
Мы увеличиваем итератор так же, как мы увеличиваем указатель на обычную C-строку. Причина, по которой эта концепция является мощной, заключается в том, что вы можете использовать шаблоны для написания функций, которые будут работать для любого типа итератора, который соответствует необходимым требованиям концепции. И это сила STL:
std::string s1 = "abcdef";
std::vector<char> buf;
std::copy(s1.begin(), s1.end(), std::back_inserter(buf));
Этот код копирует строку в вектор. copy
Функция представляет собой шаблон , который будет работать с любым итератора , который поддерживает увеличивающимся (который включает в себя простые указатели). Мы могли бы использовать ту же copy
функцию на простой C-строке:
const char* s1 = "abcdef";
std::vector<char> buf;
std::copy(s1, s1 + std::strlen(s1), std::back_inserter(buf));
Мы могли бы использовать copy
в std::map
или std::set
или любом другом контейнере, который поддерживает итераторы.
Обратите внимание, что указатели представляют собой особый тип итератора: итератор с произвольным доступом , что означает, что они поддерживают увеличение, уменьшение и продвижение с помощью оператора +
and -
. Другие типы итераторов поддерживают только подмножество семантики указателей: двунаправленный итератор поддерживает как минимум увеличение и уменьшение; а вперед итераторы поддерживает , по меньшей мере , приращение. (Все типы итераторов поддерживают разыменование.) Для copy
функции требуется итератор, который, по крайней мере, поддерживает инкремент.
Вы можете прочитать о различных концепциях итераторов здесь .
Таким образом, инкрементные указатели являются идиоматическим способом C ++ для итерации по C-массиву или доступа к элементам / смещениям в C-массиве.