2012-06-28 11 views
18

Si dice spesso che in C++ 11 sia ragionevole restituire std::vector in base al valore.Restituzione di std :: vector by value

In C++ 03 questo era principalmente vero in quanto RVO dovrebbe ottimizzare la copia. Ma questo dovrebbe spaventare la maggior parte degli sviluppatori.

  • In C++ 11 verrà sempre spostata la variabile locale std::vector?
  • Cosa succede se quel vettore è un membro di una variabile locale invece di una variabile locale stessa?
  • Ovviamente il ritorno di una variabile globale non verrà spostato. In quali altri casi non verrà spostato?
+0

Vedere anche [questa domanda] (http://stackoverflow.com/q/9532608/500104). – Xeo

risposta

15

Innanzitutto, ogni volta che una copia può essere eliminata in precedenza, è comunque possibile eliminarla ora e le mosse possono essere eliminate nelle stesse situazioni. Per il resto di questo post assumerò che elision non accada per qualche motivo (fingere che lo scrittore del compilatore fosse pigro in modo negativo).

In C++ 11 verrà sempre spostata una variabile locale std :: vector?

Ogni volta che vengono soddisfatti i criteri per l'elisione della copia o la variabile è esplicitamente std::move d.

Cosa succede se quel vettore è un membro di una variabile locale invece di una variabile locale stessa?

Non verrà spostato se non esplicitamente std::move d.

Ovviamente la restituzione di una variabile globale non verrà spostata. In quali altri casi non verrà spostato?

Ogni volta che i criteri per copia elisione non sono soddisfatti e la variabile non è esplicitamente std::move d.

Nessuno di questi è un motivo valido per non restituire in base al valore. La restituzione per valore è ok, perché anche quando il valore non viene spostato automaticamente è possibile forzarlo con std::move.

+0

Non penso che verrà spostato se può essere RVO. – juanchopanza

+0

@juanchopanza bene, sì, nessuno di questi impedisce le ottimizzazioni. –

+0

OK; il tuo primo punto sembra implicare che ** sarà ** spostato ogni volta che vengono soddisfatti i criteri per l'elisione della copia. – juanchopanza

8

In C++ 11 verrà restituita una variabile locale std::vector?

Per una variabile locale, anche un parametro per valore, il compilatore deve sempre tentativo per spostarlo prima (se né il passaggio né la copia può essere tralasciata per qualsiasi motivo, anche se i criteri sono incontrato). Se non funziona, si cerca ancora una volta con una copia:

§12.8 [class.copy] p32

Quando i criteri per l'elisione di un'operazione di copia sono stati raggiunti o sarebbero soddisfatti, salvo per il fatto che l'oggetto di origine è un parametro di funzione, e l'oggetto da copiare è designato da un lvalue, la risoluzione di sovraccarico per selezionare il costruttore per la copia viene prima eseguita come se l'oggetto fosse designato da un valore.Se la risoluzione del sovraccarico non riesce, o se il tipo del primo parametro del costruttore selezionato non è un riferimento di valore al tipo dell'oggetto (possibilmente qualificato cv), viene eseguita nuovamente la risoluzione di sovraccarico, considerando l'oggetto come un lvalue. [Nota: Questa risoluzione di sovraccarico a due stadi deve essere eseguita indipendentemente dal fatto che si verifichi l'elisione della copia. Determina il costruttore da chiamare se elision non viene eseguito e il costruttore selezionato deve essere accessibile anche se la chiamata viene eliminata. -end note]

Cosa succede se quel vettore è un membro di una variabile locale invece di una variabile locale stessa?

Non si tenta di spostare un oggetto suboject, in quanto non soddisfa i criteri per copia elision. (Che è muto, IMHO, ma è così che è attualmente. Non credo che i due dovrebbero essere collegati, in quanto un oggetto secondario può benissimo essere spostato se è locale.)

Ovviamente restituendo una variabile globale sarà non essere spostato. In quali altri casi non verrà spostato?

Un riferimento non verrà ovviamente spostato. Oltre a questo, non posso davvero pensare ad altro.

+0

Che dire di un riferimento a un locale? Cosa succede se 'std :: move' è chiamato sul riferimento locale? –

+0

@deft_code: Un riferimento in sé non verrà spostato automaticamente, sembra che la mia ultima frase non sia stata abbastanza chiara a riguardo. Un riferimento a 'std :: move' sposta l'oggetto di riferimento. – Xeo