Documenta l'effetto di std :: move

5

Mentre la mia squadra progredisce verso l'adozione delle nuove funzionalità in C ++ 11, sto cercando di rendere effettivi gli effetti collaterali di std::move di auto-documentazione nel codice.

Il problema è che un oggetto che è stato spostato non dovrebbe più essere usato dopo quel punto. Tutto quello che posso inventare è un commento:

std::string x = Func();
Other(x);   // x is zombied.

Ovviamente questo è soggetto a errori e non gestirà i casi in cui il codice più profondo potrebbe involontariamente fare un std::move .

Qualcun altro ha affrontato questo problema?

Ho la sensazione che diagnosticare l'uso di oggetti con zombi possa essere tanto doloroso quanto rintracciare perdite o danneggiamento dell'heap.

    
posta James 25.11.2013 - 11:51
fonte

2 risposte

8

Il riferimento a r si lega solo ai valori. Nel codice precedente, Other(std::string &&) sarà non essere considerato. Quindi, solo il problema potrebbe essere se la funzione std::string & ma spostata internamente.

L'unico modo per ottenere r -valore di l -valore è un std::move . Quindi, se fai attenzione a non usare std::move sull'argomento di funzione che hai ricevuto con l -valore di riferimento, non ci saranno sorprese.

Spostare qualcosa che hai ricevuto con l -valore di riferimento dovrebbe essere considerato un bug . Sfortunatamente le regole del linguaggio stesso non sono in grado di catturarlo, quindi è un lavoro per un controllore statico. Non so se qualcuno di questi lo faccia già.

Naturalmente una funzione che prende un riferimento di valore non-const l potrebbe sempre rovinare l'oggetto passato e lo spostamento aggiunge solo un altro modo per farlo, ma il problema esisteva già.

In generale, raccomanderei di evitare funzioni che assumono riferimenti a valori non const l , poiché le funzioni che modificano il loro argomento non sono mai particolarmente leggibili. Si prevede che un metodo modifichi il suo invocante (a meno che non sia un getter), ma la modifica di altri argomenti rende il flusso di dati più complicato e meno ovvio. In C ++ 11 move rende gli oggetti di ritorno efficienti quanto la modifica del riferimento e std::tuple con std::tie consente di restituire più valori, quindi la maggior parte degli usi della modifica degli argomenti può essere riscritta senza una significativa perdita di efficienza.

Come per l'uso corretto di std::move , si noti che il modo più efficace per scrivere i setter che sono stati precedentemente scritti prendendo riferimento const e copiato da esso ora dovrebbe prendere per valore e spostarsi da esso. La costruzione dell'argomento nel chiamante si muoverà se possibile e copierà altrimenti.

    
risposta data 25.11.2013 - 13:02
fonte
4

Non nascondere la mossa, scrivila così:

std::string x = Func();
Other(std::move(x));
    
risposta data 25.11.2013 - 12:18
fonte

Leggi altre domande sui tag