2016-03-18 26 views
8

Considerate questo codiceCosa si può dire del valore dei membri di tipo fondamentale spostati da un oggetto durante la costruzione del movimento?

Foo f1; 
Foo f2{ std::move(f1) }; 

mi aspetterei i valori dei membri di f1 per contenere non più necessariamente i valori indicati dal costruttore di default. Tuttavia, il test con più compilatori che utilizzano questa implementazione di Foo suggerisce diversamente.

class Foo 
{ 
public: 
    Foo() = default; 
    Foo(Foo &&) = default; 

    std::string s{ "foo" }; 
    bool t{ true }; 
    bool f{ false }; 
}; 

Dopo lo spostamento f1.t è sempre true e f1.f è sempre false. Come descritto in this question, mi aspetto che i valori siano non deterministici o che entrambi i valori booleani abbiano lo stesso valore. Tuttavia, sembrano ottenere lo stesso valore che otterrebbero dal costruttore predefinito.

Live example with GCC

E 'solo una dettagli di implementazione dei miei compilatori (per coincidenza lo stesso) o è presente nella norma?

+2

"Mi aspetto che i valori dei membri di f1 non siano inizializzati ora" Non è possibile inizializzare l'inizializzazione di qualcosa che è già stato inizializzato. – juanchopanza

+0

Puoi spostare qualcosa non inizializzato al suo posto: http://cpp.sh/5yxdt – Mathias

+0

No, sarebbe un comportamento indefinito (lettura da variabili non inizializzate). Ma il tuo esempio non lo mostra. – juanchopanza

risposta

11

Dopo lo spostamento f1.t è sempre true e f1.f è sempre false.

Per i tipi fondamentali, spostando è copia. Non vorrai che la tua implementazione copi il bool AND senza il precedente - questo è un lavoro extra non necessario. In un semplice POD, lo spostamento sarebbe solo un memcpy - ma se ciò che stai suggerendo sarebbe successo, dovresti anche fare un memset. Molto più veloce per non fare nulla.

Questo è solo un dettaglio di implementazione dei miei compilatori (per coincidenza lo stesso) o è presente nello standard?

Questo è nella norma in [class.copy]:

L'operatore di assegnazione di copia/spostamento implicitamente definito per un non-union classe X esegue membro a membro della copia assegnazione/spostamento dei suoi oggetti secondari. [...] Ogni sottobooggetto è assegnato nel modo appropriato al suo tipo:
- [...]
- se il sottooggetto è di tipo scalare, viene utilizzato l'operatore di assegnazione incorporato.