2015-11-20 18 views
5

Supponiamo che ho struct Foo con mossa constructor e operator=(Foo&&), e ho usato come membro di dati:C++ std :: move is bad here?

Foo f() 
{ 
    Foo foo; 
    //code 
    return foo; 
} 
struct Boo { 
Foo foo; 
Boo() { 
    foo = f();//1 
    foo = std::move(f());//2 
} 
}; 

In caso (2) Io in realtà non hanno bisogno std::move, ma se l'ho usato qui , questo fa qualcosa di male, come prevenire l'ottimizzazione?

ho letto questo: Why does std::move prevent RVO?

e scoprire che la modifica return foo;-return std::move(foo); causa disabilitazione di RVO, ma per quanto riguarda (2) lo fa causa alla situazione simile? E se sì, perché?

+7

Copia elisione non si applica in questo caso comunque perché si sta chiamando 'foo.operator ='. Sarebbe rilevante se tu avessi "Foo foo = std :: move (f());" che è l'inizializzazione. –

+1

@ M.M Ma 'clang 3.7' avverto su questo, quindi mi chiedo, è un bug nella generazione di avvisi, o mi sono perso qualcosa – user1244932

+1

Può essere negativo per motivi che non sono anche motivi di prestazioni. Nel tuo caso per # 2, tieni a chiamare std :: move (f()) su qualcosa che è già un rhr, quindi la mossa è sprecata caratteri. La mia regola generale è che dovresti evitare std :: move a meno che non sia necessario, e devi farlo solo quando trasferisci la proprietà in modo non banale. – IdeaHat

risposta

5

È ridondante e confuso. Solo perché posso scrivere std::add_pointer_t<void> anziché void* o std::add_lvalue_reference_t<Foo> (o Foo bitand) anziché Foo&, non significa che dovrei.

è importante anche in altri contesti:

auto&& a = f(); // OK, reference binding to a temporary extends its lifetime 
auto&& b = std::move(f()); // dangling 

e così, se Foo è qualcosa che può essere iterato,

for(const auto& p : f()) {} // OK 
for(const auto& p : std::move(f())) {} // UB 

E nel tuo esempio, se l'operatore di assegnazione è implementato come copy-and-swap (operator=(Foo)), quindi foo = std::move(f()) forza una mossa non eliminabile, mentre foo = f() può rimuovere il passaggio dal valore f() all'argomento operator=.

+0

In questo primo esempio, 'b' NON sembra ciondolare quando compilato da' VS2013'. (Non ho ancora provato con nessun altro compilatore). Potresti fornire qualche informazione in più su questo? –

+0

@DeanSeo Né [clang] (http://coliru.stacked-crooked.com/a/607b0d720af30b9e) né [gcc] (http://coliru.stacked-crooked.com/a/698d5c5271c8f1c8) estenderanno la durata di il temporaneo. Il primo emetterà anche alcuni avvertimenti sul rendimento. –

+0

@ MatthäusBrandl Non penso che 'std :: move (f())' sia ancora temporaneo, ma probabilmente verrà spostato molto presto come valore x. Quindi non è ancora stato spostato ...? (significato non penzolanti). L'ho postato molto tempo fa, quindi forse ho bisogno di tempo per recuperare. –

Problemi correlati