Разница в этих примерах скрыта внутри правил передачи параметров функциям.
В первом примере, когда вы пишете int ar[] = {1, 2, 3};
, тип ar
равен int[3]
- "an массив из 3-х целых ". std::begin
определен для массивов, поэтому код компилируется и работает.
Во втором примере char const *argv[]
на самом деле то же самое, что char const **argv
, потому что в параметрах функции вы не можете передать массив по значению , а синтаксис []
компилируется точно так же, как если бы вы использовали *
. Очевидно, что для указателей нет std::begin
, поэтому код не работает.
Чтобы перебрать аргументы, вам нужно будет использовать обычное для l oop. Например,
for (int i = 0; i < argc; ++i) {
char const* arg = argv[i];
};
Edit: просто для пояснения - для использования диапазона l oop, std::begin(a)
и std::end(a)
должны быть вызываемыми и возвращать итератор. (не совсем верно, поскольку C ++ 17 - std::end
может возвращать все, что сравнимо с итератором, это называется часовым в рабочем проекте C ++ 20)
В случай массива с известной границей (например, int[3]
), std::begin
возвращает указатель на первый элемент, а std::end
возвращает указатель за концом. iterator
в C ++ не обязательно должен быть производным классом какой-то специальной базы, он просто должен иметь правильную семантику. Указатели также являются итераторами .