Isso é realmente difícil de explicar, mas vou tentar ...
Em primeiro lugar, dimof
informa a dimensão ou o número de elementos em uma matriz. (Eu acredito que "dimensão" é a terminologia preferida nos ambientes de programação do Windows).
Isso é necessário porque C++
e C
não fornece uma maneira nativa de determinar o tamanho de uma matriz.
Muitas vezes, as pessoas assumem sizeof(myArray)
que funcionará, mas isso realmente fornecerá o tamanho da memória, e não o número de elementos. Cada elemento provavelmente leva mais de 1 byte de memória!
Em seguida, eles podem tentar sizeof(myArray) / sizeof(myArray[0])
. Isso daria o tamanho na memória da matriz, dividido pelo tamanho do primeiro elemento. Está tudo bem, e amplamente usado em C
código. O principal problema disso é que ele parecerá funcionar se você passar um ponteiro em vez de uma matriz. O tamanho de um ponteiro na memória geralmente será de 4 ou 8 bytes, mesmo que o item para o qual ele aponta possa ser uma matriz de 1000s de elementos.
Portanto, a próxima coisa a experimentar C++
é usar modelos para forçar algo que só funciona para matrizes e fornecerá um erro de compilador em um ponteiro. Se parece com isso:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
O modelo funcionará apenas com uma matriz. Deduzirá o tipo (não é realmente necessário, mas precisa estar lá para que o modelo funcione) e o tamanho da matriz e, em seguida, retornará o tamanho. A maneira como o modelo é escrito não pode funcionar com um ponteiro.
Geralmente você pode parar por aqui, e isso está no C ++ Standard Libary como std::size
.
Atenção: aqui embaixo entra em território peludo-advogado de línguas.
Isso é bem legal, mas ainda falha em um caso de borda obscuro:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
Observe que a matriz x
é declarada , mas não definida . Para chamar uma função (ou seja ArraySize
) com ela, x
deve ser definido .
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
Você não pode vincular isso.
O código que você tem na pergunta é uma maneira de contornar isso. Em vez de realmente chamar uma função, declaramos uma função que retorna um objeto exatamente do tamanho certo . Então nós usamos o sizeof
truque nisso.
Ele olha como nós chamamos a função, mas sizeof
é puramente uma construção tempo de compilação, assim que a função nunca realmente é chamado.
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
^^^^ ^ ^^^
// a function that returns a reference to array of N chars - the size of this array in memory will be exactly N bytes
Observe que você não pode realmente retornar uma matriz de uma função, mas pode retornar uma referência a uma matriz.
Então DimofSizeHelper(myArray)
é uma expressão cujo tipo é uma matriz emN
char
s. A expressão não precisa ser executável, mas faz sentido em tempo de compilação.
Portanto sizeof(DimofSizeHelper(myArray))
, informará o tamanho em tempo de compilação do que você obteria se realmente chamasse a função. Mesmo que na verdade não chamemos isso.
Não se preocupe se esse último bloco não fizer sentido. É um truque bizarro contornar um caso estranho. É por isso que você não escreve esse tipo de código e deixa os implementadores de bibliotecas se preocupar com esse tipo de bobagem.
std::array
oustd::vector
....