2012-06-08 9 views
7

Questo è puramente ipotetico, ma non sono sicuro se il codice seguente produrrà un comportamento indefinito secondo le specifiche C++. Mi piacerebbe fare una copia dei byte in un oggetto, far saltare l'oggetto sovrascrivendolo con zeri, quindi copiare i vecchi byte indietro. Posso farlo senza causare un comportamento indefinito?Posso clonare i byte di un oggetto C++, sovrascrivere i byte originali, quindi copiare nuovamente quei byte?

codice di esempio:

NonPODType o; 
char bytes[sizeof(o)]; 

memcpy(bytes, &o, sizeof(o)); 
memset(&o, 0, sizeof(o)); 
memcpy(&o, bytes, sizeof(o)); 
+1

Non penserei che causerebbe problemi strani, ma perché lo faresti? Dalla mia comprensione, il risultato netto è pari a zero –

+1

Interessante domanda. Se la risposta è effettivamente "No", sarebbe interessante vedere un esempio specifico che non funziona. Naturalmente, un tale esempio potrebbe non esistere nelle attuali implementazioni. –

+0

Si interrompe definitivamente per una classe con membri volatili (poiché lo stato può cambiare tra copia e imposta). –

risposta

9

In generale, no. Esiste una garanzia esplicita che questo funziona per i tipi banalmente copiabili al §3.9/2, ma non esiste una cosa del genere per altri tipi.

Per qualsiasi oggetto (diverso da un sotto-oggetto classe base) di banalmente tipo copiabile T, se l'oggetto contiene un valore valido di tipo T, i byte sottostanti (1,7) costituenti l'oggetto può essere copiati in un array di char o unsigned char. Se il contenuto dell'array di char o unsigned char viene copiato nuovamente nell'oggetto, l'oggetto deve mantenere successivamente il suo valore originale. [Esempio:

#define N sizeof(T) 
char buf[N]; 
T obj; 
// obj initialized to its original value 
std::memcpy(buf, &obj, N); 
// between these two calls to std::memcpy, 
// obj might be modified 
std::memcpy(&obj, buf, N); 
// at this point, each subobject of obj of scalar type 
// holds its original value 

-end esempio]

+0

+1 Preventivo perfetto con codice-snippet perfetto. – Nawaz

+0

Fantastico! Detto questo, sai cosa spezza specificamente se T non è banalmente riproducibile? – templatetypedef

+0

@templatetypedef Ho cercato di trovare qualche ragione per cui si sarebbe interrotto, ma, a meno che tu non acceda ai byte copiati, ho problemi a trovare un esempio convincente (che non implichi un'ipotetica implementazione di Hell ++). Non so se questo è solo a causa della mia mancanza di immaginazione. –

1

In generale, sì. L'unico modo in cui le cose si interrompono è se si accede all'oggetto dopo aver distrutto l'oggetto e prima della restituzione dei suoi dati:

memset (& o, 0, sizeof (o));

obj.doSomething(); < --- interruzioni

memcpy (& o, byte, sizeof (o));

+0

Stavo partendo dal presupposto che non ci siano operazioni intermedie sull'oggetto mentre i suoi byte sono stati temporaneamente distrutti. Ma grazie per averlo indicato! – templatetypedef

+0

Qualunque cosa proibisce a un'implementazione C++ di mantenere un elenco collegato di * tutti * oggetti non POD e di scansionare quell'elenco ogni volta che qualsiasi cosa in memoria viene modificata (ma riguardo alle modifiche generate dal compilatore alla struttura come atomiche)? Una cosa del genere sarebbe orribilmente lenta, naturalmente, ma qualcosa lo proibirebbe? – supercat

Problemi correlati