c++ - sesion - matlab usuario
¿Cómo sabe std:: end el final de una matriz? (3)
std::begin
y
std::end
conocen el principio y el final de un
container
o una
array
.
Es muy fácil saber el
end
y el
begin
de un
vector
por ejemplo, porque es una clase que proporciona esta información.
Pero, ¿cómo sabe el final de una
array
como la siguiente?
int simple_array[5]{1, 2, 3, 4, 5};
auto beg=std::begin(simple_array);
auto en=std::end(simple_array);
std::begin
no es tan difícil saber dónde comienza la matriz.
Pero, ¿cómo sabe dónde termina?
¿Se almacenará el entero constante
5
alguna parte?
Agradecería si obtuviera una respuesta con información de bajo nivel.
Pero, ¿cómo sabe el final de una matriz?
Utiliza un parámetro de plantilla que no es de tipo para deducir el tamaño de la matriz, que luego se puede usar para generar el puntero final. La firma C ++ 11 de la sección cppreference para std::end es la siguiente:
template< class T, std::size_t N >
T* end( T (&array)[N] );
Como señala hvd, dado que se pasa por referencia, esto evita la descomposición de un puntero.
La implementación sería algo similar a:
template< class T, std::size_t N >
T* end( T (&array)[N] )
{
return array + N ;
}
¿El entero constante 5 se almacenará en algún lugar?
5
o
N
es parte del tipo de matriz y, por lo tanto,
N
está disponible en tiempo de compilación.
Por ejemplo, aplicar
sizeof
a una matriz nos dará el número total de bytes en la matriz.
Muchas veces vemos una matriz pasada por valor a una función.
En ese caso, la matriz se
descompone en un puntero
para escribir almacenada en la matriz.
Entonces ahora se pierde la información del tamaño.
Pasar por referencia nos permite evitar esta pérdida de información y extraer el tamaño
N
del tipo.
es el entero constante 5 se almacenará en algún lugar?
Sí, es parte del tipo de matriz. Pero no, no se almacena en ningún lugar explícitamente. Cuando tengas
int i[5] = { };
el tipo de
i
es
int[5]
.
La respuesta de Shafik habla sobre cómo se usa esta longitud para implementar el
end
.
Si tiene C ++ 11, usar
constexpr
sería la forma más sencilla de hacerlo
template <typename T, size_t N>
inline constexpr size_t
arrLen(const T (&arr) [N]) {
return N;
}
Si tiene un compilador anterior a C ++ 11 donde
constexpr
no está disponible, la función anterior puede no evaluarse en tiempo de compilación.
Entonces, en tales situaciones, puede usar esto:
template <typename T, size_t N>
char (&arrLenFn(const T (&arr) [N]))[N];
#define arrLen(arr) sizeof(arrLenFn(arr))
Primero declaramos que una función devuelve una referencia a una matriz de N caracteres, es decir, el
sizeof
esta función ahora sería la longitud de la matriz.
Luego tenemos una macro para envolverlo, de modo que sea legible al final de la persona que llama.
Nota:
Dos matrices del mismo tipo base pero con diferentes longitudes siguen siendo dos tipos completamente diferentes.
int[3]
no es lo mismo que
int[2]
.
Sin embargo, la
descomposición de la matriz le
daría un
int*
en ambos casos.
Leer
¿Cómo uso matrices en C ++?
si quieres saber más
Porque está pasando una matriz a
std::end
, y una matriz tiene el tipo
T [N]
.
std::end
puede decir cuándo termina la matriz mirando la
N
en el tipo.