Подтвердить что ты не робот

Как std:: end знает конец массива?

std::begin и std::end знать начало и конец container или array.

Так легко знать end и begin для vector, например, потому что это класс, который дает эту информацию. Но как он знает конец array, как показано ниже?

int simple_array[5]{1, 2, 3, 4, 5};
auto beg=std::begin(simple_array);
auto en=std::end(simple_array);

std::begin не так сложно узнать, где начинается массив. Но откуда он знает, где это заканчивается? Будет ли где-нибудь сохранено постоянное целое число 5?

Я был бы признателен, если бы получил ответ с информацией о низком уровне.

4b9b3361

Ответ 1

- постоянное целое число 5 будет сохранено где-нибудь, где?

Да, это часть типа массива. Но нет, он не хранится нигде явно. Когда у вас

int i[5] = { };

тип i равен int[5]. Ответ Shafik говорит о том, как эта длина используется для реализации end.

Если у вас С++ 11, использование constexpr будет простым способом

template <typename T, size_t N>
inline constexpr size_t
arrLen(const T (&arr) [N]) {
    return N;
}

Если у вас есть компилятор pre-С++ 11, где constexpr недоступен, указанная выше функция не может быть оценена во время компиляции. Поэтому в таких ситуациях вы можете использовать это:

template <typename T, size_t N>
char (&arrLenFn(const T (&arr) [N]))[N];

#define arrLen(arr) sizeof(arrLenFn(arr))

Сначала мы объявляем функцию, возвращающую ссылку на массив из N char i.e. sizeof эта функция теперь будет длиной массива. Затем у нас есть макрос, чтобы его обернуть, чтобы он читался в конце звонящего.

Примечание. Два массива одного и того же базового типа, но с разной длиной, все еще два совершенно разных типа. int[3] не совпадает с int[2]. Array decay, однако, даст вам int* в обоих случаях. Прочитайте Как использовать массивы на С++?, если вы хотите узнать больше.

Ответ 2

Но как он знает конец массива

Он использует параметр non-type шаблона, чтобы вывести размер массива, который затем можно использовать для создания конечного указателя. Подпись С++ 11 из раздела cppreference для std:: end выглядит следующим образом:

template< class T, std::size_t N >
T* end( T (&array)[N] );

Как отмечает hvd, поскольку он передается по ссылке, это предотвращает распад указателя.

Реализация будет похожа на:

template< class T, std::size_t N >
T* end( T (&array)[N] )
{
    return array + N ;
}

Будет ли сохранено постоянное целое число 5 где?

5 или N является частью типа массива, поэтому N доступен во время компиляции. Например, применение sizeof к массиву даст нам общее количество байтов в массиве.

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

Ответ 3

Поскольку вы передаете массив в std::end, а массив имеет тип T [N]. std::end может определить, когда массив закончится, посмотрев на N в типе.