Diciamo che ho due vettori e che mi muovo l'uno con l'altro, v1 = std::move(v2)
; sarà v2
ancora in uno stato utilizzabile dopo questo?Il movimento lascia l'oggetto in uno stato utilizzabile?
risposta
Da n3290, 17.6.5.15 Spostato-da stato di tipi di libreria [lib.types.movedfrom]
- Oggetti di tipo definito nella libreria standard C++ possono essere spostati da (12.8) . Le operazioni di spostamento possono essere specificate in modo esplicito o generate implicitamente. Se non diversamente specificato, tali oggetti spostati da devono essere collocati in uno stato valido ma non specificato.
Poiché lo stato è valido, questo significa che è possibile operare in sicurezza sul v2
(ad esempio assegnando ad esso, che avrebbe messo di nuovo a uno stato noto). Tuttavia, poiché non è specificato, significa che non è possibile, ad esempio, fare affidamento su alcun valore particolare per v2.empty()
finché si trova in questo stato (ma chiamarlo non bloccherà il programma).
Si noti che questo assioma della semantica del movimento ("Spostato dagli oggetti è lasciato in uno stato valido ma non specificato") è qualcosa su cui tutto il codice deve mirare (il più delle volte), non solo i componenti della Libreria standard. Molto simile alla semantica dei costruttori di copie dovrebbe essere fare una copia, ma non vengono applicate a.
+1, ma come è scritto, sembra che tu non sappia se 'v2' è vuoto dopo' v2 = std :: vector {}; ' – Gabriel
@Gabriel Un buon punto, una modifica è in ordine. –
No, viene lasciato in uno stato non specificato.
Estratto open-std-org articolo -
.. mossa() dà il suo obiettivo il valore del suo argomento, ma è non è obbligato a preservare il valore della sua fonte. Quindi, per un vettore, si può ragionevolmente pensare che move() lasci la sua argomentazione come vettore a capacità zero per evitare di dover copiare tutti gli elementi. In altre parole, spostare è una lettura potenzialmente distruttiva.
Viene lasciato in uno stato _but valid_ non specificato. Cioè, puoi ancora usare l'oggetto in modi che hanno solo il presupposto che l'oggetto sia valido. Ad esempio, è possibile chiamare vector :: clear() su quel vettore spostato da per portarlo in uno stato noto e quindi iniziare a inserire oggetti in esso. – bames53
È __poco__ essere valido. Altrimenti cosa succederebbe quando l'oggetto uscisse dall'ambito.Molto probabilmente non avrà nulla nel suo datastore, ma qualunque cosa sia, sarà valido. – Damon
Ci sono più livelli (astratti) di validità. Per quanto riguarda la lingua, l'oggetto dopo essere stato spostato è valido fino a quando l'oggetto esiste ancora, il suo distruttore può essere chiamato senza causare un comportamento indefinito, ecc. Il contratto dell'oggetto, tuttavia, può essere modificato a causa dello spostamento . Ad esempio, il fatto che un vettore sia diventato zero (non avendo una capacità) è un vettore C++ valido, ma un oggetto che ha un metodo che imposta un particolare elemento sul vettore, senza verificare l'ipotesi (ora invalidata) che il il vettore dovrebbe avere una dimensione particolare, diventa ... – rwong
Se desidera utilizzare v2 dopo lo spostamento, si vuole fare qualcosa di simile:
v1 = std::move(v2);
v2.clear();
A questo punto, v1 avrà il contenuto originale del v2 e v2 sarà in un pozzo -Stato vuoto definito. Funziona su tutti i contenitori STL (e le stringhe, se è per questo) e se stai implementando le tue classi che supportano la semantica del movimento, probabilmente vorrai fare qualcosa di simile.
Se la vostra particolare implementazione del STL effettivamente lascia l'oggetto in uno stato vuoto, il secondo clear() sarà essenzialmente un no-op. Infatti, se questo è il caso, sarebbe un ottimizzazione legale per un compilatore eliminare il clear() dopo lo spostamento.
Questo sembra un duplicato di http://stackoverflow.com/q/7027523/576911. Vedere questa risposta: http://stackoverflow.com/questions/7027523/what-can-i-do-with-a-moved-from-object/7028318#7028318 a quella domanda che tratta delle operazioni consentite in termini di condizioni preliminari. –