2016-01-22 19 views
6

Sono po 'perplesso su come governa standard di questo caso:std :: movimento e mappa assegnazione

struct Foo { 
    Foo & operator = (std::string xxx) 
    { 
     x = std::move(xxx); 
     return *this; 
    } 

    std::string x; 
}; 

std::map<std::string, Foo> bar; 

std::string baz = "some string"; 

bar[baz] = std::move(baz); 

Può compilatori produrre codice in modo che baz saranno spostati prima è usato per inizializzare e ottenere di riferimento all'elemento in bar (per inizializzare std::string xxx)? O questo codice è sicuro e non c'è il comportamento non definito ?

+1

Non è UB, ma non garantito per funzionare, neanche. –

+0

Vedere [this] (http://coliru.stacked-crooked.com/a/5ef8993192148d84) versione semplificata del codice. 'std :: map' e l'operatore di assegnazione non devono essere coinvolti affinché ciò avvenga e la loro presenza non modifica il problema sottostante con il codice. – Mankarse

+0

@Mankarse, sì, infatti, tutto può essere ridotto a questo caso – GreenScape

risposta

11

Inferno no. L'espressione è, sì, equivalente a

(bar.operator[](baz)).operator=(std::move(baz)) 

Ma non c'è ordine garantito tra la valutazione dei (bar.operator[](baz)).operator= - formalmente, il postfix-espressione designa la funzione da chiamare - e la valutazione della inizializzazione del argomento a operator=, che è ciò che si sposta da baz.

Infatti, this asserts on GCC:

std::map<std::string, Foo> bar; 
std::string baz = "some string"; 
bar[baz] = std::move(baz); 
assert(bar.count("some string")); 
+1

Grazie! Questo è quello che pensavo, volevo solo una conferma da qualcun altro. – GreenScape