Questo in realtà è molto difficile da spiegare, ma ci proverò ...
Innanzitutto, dimof
indica la dimensione o il numero di elementi in un array. (Credo che "dimensione" sia la terminologia preferita negli ambienti di programmazione di Windows).
Questo è necessario perché C++
e C
non ti dà un modo nativo per determinare la dimensione di un array.
Spesso le persone credono sizeof(myArray)
che funzionerà, ma che in realtà ti darà la dimensione in memoria, piuttosto che il numero di elementi. Ogni elemento probabilmente richiede più di 1 byte di memoria!
Successivamente, potrebbero provare sizeof(myArray) / sizeof(myArray[0])
. Ciò darebbe la dimensione in memoria dell'array, divisa per la dimensione del primo elemento. È ok e ampiamente usato nel C
codice. Il problema principale con questo è che sembrerà funzionare se si passa un puntatore anziché un array. La dimensione di un puntatore in memoria sarà generalmente di 4 o 8 byte, anche se la cosa a cui punta potrebbe essere una matrice di migliaia di elementi.
Quindi la prossima cosa da provare C++
è usare i template per forzare qualcosa che funziona solo per gli array, e darà un errore del compilatore su un puntatore. Sembra così:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
Il modello funzionerà solo con un array. Ne dedurrà il tipo (non proprio necessario, ma deve essere lì per far funzionare il modello) e la dimensione dell'array, quindi restituisce la dimensione. Il modo in cui il modello è scritto non può funzionare con un puntatore.
Di solito puoi fermarti qui, e questo è nella C ++ Standard Libary come std::size
.
Attenzione: qui sotto entra nel territorio peloso di avvocato linguistico.
Questo è piuttosto interessante, ma fallisce comunque in un caso oscuro:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
Si noti che l'array x
è dichiarato , ma non definito . Per chiamare una funzione (cioè ArraySize
) con essa, x
deve essere definito .
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
Non puoi collegarlo.
Il codice che hai nella domanda è un modo per aggirare quello. Invece di chiamare effettivamente una funzione, dichiariamo una funzione che restituisce un oggetto della giusta dimensione . Quindi usiamo il sizeof
trucco su questo.
E sembra come noi chiamiamo la funzione, ma sizeof
è puramente un costrutto fase di compilazione, quindi la funzione non viene effettivamente chiamato.
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
Nota che non puoi effettivamente restituire un array da una funzione, ma puoi restituire un riferimento a un array.
Quindi DimofSizeHelper(myArray)
è un'espressione il cui tipo è un array su N
char
s. In realtà l'espressione non deve essere eseguibile, ma ha senso al momento della compilazione.
Pertanto sizeof(DimofSizeHelper(myArray))
ti dirà la dimensione in fase di compilazione di ciò che otterresti se in realtà chiamassi la funzione. Anche se in realtà non lo chiamiamo.
Non preoccuparti se l'ultimo blocco non avesse alcun senso. È un trucco bizzarro aggirare un bizzarro caso limite. Questo è il motivo per cui non scrivi tu stesso questo tipo di codice e lasci che gli implementatori di librerie si preoccupino di questo tipo di sciocchezze.
std::array
ostd::vector
...