2015-12-23 20 views
20

A POD struct può essere zero-inizializzati in C++ 11 come segue:Zero-reinizializzazione una struct in C++

SomeStruct s{}; 

Tuttavia, cosa faccio se ho già un'istanza della struct e vuoi inizializzarlo di nuovo a zero? Quanto segue sembra funzionare:

s = {}; 

Qualcuno può indicare la standardese rilevante? Presumo questo è ciò che sta accadendo:

  1. Viene creata una nuova istanza inizializzata a zero.
  2. La nuova istanza viene assegnata all'istanza esistente, richiamando l'operatore di assegnazione implicita.
+1

Non conosco lo standard, ma - alcuni di questi potrebbero essere ottimizzati. Infatti, se non usi gli 0, forse tutto questo è ottimizzato. – einpoklum

+1

C'è una regola esplicita in là che consente le parentesi sulla mano destra di un compito. La tua ipotesi è praticamente corretta. – chris

+0

Non esiste una "reinizializzazione". Inizializzi qualcosa una volta. Solo una volta. Quello che stai facendo è un incarico ed è molto diverso in modi sottili e non così sottili. –

risposta

18

Quello che state cercando è in [expr.ass]

A rinforzato-init-list può apparire sul lato destro della

  • l'incarico di uno scalare, nel qual caso l'elenco di inizializzazione deve avere al massimo un singolo elemento. Il significato di x={v}, dove T è il tipo scalare dell'espressione x, è quello di x=T{v}. Il significato di x={} è x=T{}.
  • un'assegnazione a un oggetto di tipo classe, nel qual caso l'elenco di inizializzazione viene passato come argomento a la funzione dell'operatore di assegnazione selezionata dalla risoluzione di sovraccarico (13.5.3, 13.3).

Quindi la tua ipotesi è corretta. Il compilatore può essere in grado di ottimizzare le cose, ma puoi pensarci come creare un temporaneo inizializzato a zero e passarlo allo operator=.

12

s = {}; non è sicuro.

Il problema è che si si spera diventa s = SomeStruct{};. Tuttavia, se s ha un altro sovraccarico per operator=then that may be preferred by overload resolution.

Quindi questo è un anti-pattern, davvero. Come suggerito in altro thread, è meglio scrivere una funzione, ad es .:

template<typename T> void reset(T &t) { t = T{}; } 

Credo che si potrebbe anche scrivere s = decltype(s){};, purché s non era un punto di riferimento.

+1

Perché non usare esplicitamente la tua 'sperata' per la risoluzione. 's = SomeStruct {}'? Sembra più chiaro di una chiamata a 'reset()'. –

+1

@LokiAstari beh, potremmo essere lontani dalla dichiarazione di 's' quindi non è così facile verificare che questo faccia effettivamente la cosa giusta. Se mettiamo accidentalmente 's = SomeOtherStruct {};' allora potrebbero accadere altri effetti strani. Cerco di utilizzare modelli di codice che riducano al minimo la possibilità di errori (in particolare, errori non ovvi). Suppongo che la versione 'decltype' sia la migliore. Lo trovo antiestetico ma forse ho bisogno di aggiornare la mia estetica –

+0

Prendo il vostro punto su 'SomeOtherStruct {}'. Quindi ha più senso per il 'decltype', ma sembra ancora brutto (e l'estetica è importante). –