C++
Allineamento
Ricerca…
introduzione
Tutti i tipi in C ++ hanno un allineamento. Questa è una restrizione sull'indirizzo di memoria che gli oggetti di quel tipo possono essere creati all'interno. Un indirizzo di memoria è valido per la creazione di un oggetto se la divisione di quell'indirizzo tramite l'allineamento dell'oggetto è un numero intero.
Gli allineamenti di tipo sono sempre una potenza di due (incluso 1).
Osservazioni
Lo standard garantisce quanto segue:
- Il requisito di allineamento di un tipo è un divisore delle sue dimensioni. Ad esempio, una classe con dimensione 16 byte potrebbe avere un allineamento di 1, 2, 4, 8 o 16, ma non 32. (Se i membri di una classe hanno solo 14 byte di dimensione, la classe deve avere un requisito di allineamento di 8, il compilatore inserirà 2 byte di riempimento per rendere la dimensione della classe uguale a 16.)
- Le versioni firmate e non firmate di un tipo intero hanno lo stesso requisito di allineamento.
- Un puntatore a
void
ha lo stesso requisito di allineamento di un puntatore alchar
. - Le versioni cv-qualificate e cv-non qualificate di un tipo hanno lo stesso requisito di allineamento.
Si noti che mentre l'allineamento esiste in C ++ 03, non è stato fino a C ++ 11 che è diventato possibile interrogare l'allineamento (usando alignof
) e l'allineamento di controllo (usando alignas
).
Interrogare l'allineamento di un tipo
Il requisito di allineamento di un tipo può essere interrogato utilizzando la parola chiave alignof
come operatore unario. Il risultato è un'espressione costante di tipo std::size_t
, cioè può essere valutata in fase di compilazione.
#include <iostream>
int main() {
std::cout << "The alignment requirement of int is: " << alignof(int) << '\n';
}
Uscita possibile
Il requisito di allineamento di int è: 4
Se applicato a un array, restituisce il requisito di allineamento del tipo di elemento. Se applicato a un tipo di riferimento, restituisce il requisito di allineamento del tipo di riferimento. (I riferimenti stessi non hanno allineamento, dal momento che non sono oggetti.)
Controllo dell'allineamento
La parola chiave alignas
può essere utilizzata per forzare una variabile, un membro di dati di classe, una dichiarazione o definizione di una classe, o una dichiarazione o una definizione di enum, per avere un particolare allineamento, se supportato. Si presenta in due forme:
-
alignas(x)
, dovex
è un'espressione costante, dà all'entità l'allineamentox
, se supportato. -
alignas(T)
, doveT
è un tipo, dà all'entità un allineamento uguale al requisito di allineamento diT
, cioèalignof(T)
, se supportato.
Se più alignas
sono applicati alla stessa entità, si applica la più severa.
In questo esempio, è garantito che il buffer buf
sia allineato in modo appropriato per contenere un oggetto int
, anche se il suo tipo di elemento è unsigned char
, che potrebbe avere un requisito di allineamento più debole.
alignas(int) unsigned char buf[sizeof(int)];
new (buf) int(42);
alignas
non può essere usato per dare a un tipo un allineamento più piccolo di quello che avrebbe il tipo senza questa dichiarazione:
alignas(1) int i; //Il-formed, unless `int` on this platform is aligned to 1 byte.
alignas(char) int j; //Il-formed, unless `int` has the same or smaller alignment than `char`.
alignas
, quando viene fornita un'espressione costante intera, devono avere un allineamento valido. Gli allineamenti validi sono sempre poteri di due e devono essere maggiori di zero. I compilatori sono tenuti a supportare tutti gli allineamenti validi fino all'allineamento del tipo std::max_align_t
. Possono supportano allineamenti grandi di questo, ma il supporto per l'allocazione di memoria per tali oggetti è limitata. Il limite superiore per gli allineamenti dipende dall'implementazione.
C ++ 17 offre un supporto diretto per l' operator new
per l'allocazione della memoria per i tipi sovradimensionati.