La confusione è che C consente esplicitamente la punzonatura di tipo attraverso un sindacato, mentre C ++ (c ++ 11) non ha tale permesso.
c11
6.5.2.3 Struttura e membri del sindacato
95) Se il membro utilizzato per leggere il contenuto di un oggetto unione non è lo stesso dell'ultimo membro utilizzato per memorizzare un valore nell'oggetto, la parte appropriata della rappresentazione dell'oggetto del valore viene reinterpretata come rappresentazione dell'oggetto nel nuovo digitare come descritto in 6.2.6 (un processo talvolta chiamato '' punzonatura ''). Questa potrebbe essere una rappresentazione trappola.
La situazione con C ++:
c ++ 11
9.5 Unions [class.union]
In un'unione, al massimo uno dei membri di dati non statici può essere attivo in qualsiasi momento, ovvero il valore di al massimo uno dei membri di dati non statici può essere archiviato in un'unione in qualsiasi momento.
C ++ in seguito ha un linguaggio che consente l'uso di sindacati contenenti struct
s con sequenze iniziali comuni; ciò non consente tuttavia la punitura di tipo.
Per determinare se la punzonatura dei tipi di unione è consentita in C ++, dobbiamo cercare ulteriormente. Richiama questoc99 è un riferimento normativo per C ++ 11 (e C99 ha un linguaggio simile a C11 che consente la punitura dei tipi di unione):
3.9 Tipi [tipi di base]
4 - La rappresentazione dell'oggetto di un oggetto di tipo T è la sequenza di N oggetti char senza segno ripresi dall'oggetto di tipo T, dove N è uguale a sizeof (T). La rappresentazione di valore di un oggetto è l'insieme di bit che contengono il valore di tipo T. Per tipi banalmente copiabili, la rappresentazione di valore è un insieme di bit nella rappresentazione di oggetto che determina un valore, che è un elemento discreto di un'implementazione- set di valori definito. 42
42) L'intento è che il modello di memoria di C ++ sia compatibile con quello del linguaggio di programmazione C. ISO / IEC 9899
Diventa particolarmente interessante quando leggiamo
3.8 Durata dell'oggetto [basic.life]
La durata di un oggetto di tipo T inizia quando: - si ottiene una memoria con il corretto allineamento e dimensione per il tipo T e - se l'oggetto ha un'inizializzazione non banale, la sua inizializzazione è completa.
Quindi per un tipo primitivo (che ipso facto ha una banale inizializzazione) contenuto in un'unione, la durata dell'oggetto comprende almeno la durata dell'unione stessa. Questo ci consente di invocare
3.9.2 Tipi di composti [basic.compound]
Se un oggetto di tipo T si trova su un indirizzo A, un puntatore di tipo cv T * il cui valore è l'indirizzo A punta a quell'oggetto, indipendentemente da come è stato ottenuto il valore.
Supponendo che l'operazione a cui siamo interessati sia la punzonatura del tipo, cioè prendendo il valore di un membro sindacale non attivo, e dato quanto sopra che abbiamo un riferimento valido all'oggetto a cui fa riferimento quel membro, tale operazione è lvalue-to -valutazione conversione:
4.1 Conversione da valore in valore [conv.lval]
Un valore nominale di un tipo non funzionale, non array T
può essere convertito in un valore. Se T
è un tipo incompleto, un programma che richiede questa conversione è mal formato. Se l'oggetto a cui si riferisce il valore gluteo non è un oggetto di tipo T
e non è un oggetto di un tipo derivato T
o se l'oggetto non è inizializzato, un programma che richiede questa conversione ha un comportamento indefinito.
La domanda quindi è se un oggetto che è un membro del sindacato non attivo viene inizializzato dalla memoria sul membro del sindacato attivo. Per quanto posso dire, questo non è il caso e quindi anche se:
- un'unione viene copiata nella
char
memoria dell'array e viceversa (3.9: 2), oppure
- un'unione viene copiata per byte in un'altra unione dello stesso tipo (3.9: 3), oppure
- a un sindacato si accede attraverso i confini del linguaggio da un elemento del programma conforme a ISO / IEC 9899 (per quanto definito) (3.9: 4 nota 42), quindi
l'accesso a un'unione da parte di un membro non attivo è definito ed è definito per seguire l'oggetto e la rappresentazione del valore, l'accesso senza una delle interposizioni sopra è un comportamento indefinito. Ciò ha implicazioni per le ottimizzazioni che possono essere eseguite su un tale programma, poiché l'implementazione può ovviamente presumere che non si verifichino comportamenti indefiniti.
Cioè, anche se possiamo legittimamente formare un valore per un membro del sindacato non attivo (motivo per cui l'assegnazione a un membro non attivo senza costruzione è ok) è considerato non inizializzato.