2013-05-09 12 views
7

In C++, se si dispone di un ciclo for che "copie" oggetti di un tipo definito dall'utente utilizzando un costruttore mossa, Fa qualche differenza se si utilizza ++i o i++ come il contatore di loop?Spostare costruttore e di pre-incremento vs post-incremento

So che questa domanda sembra piuttosto vaga, ma sono stato (credo) a chiederlo in un'intervista telefonica. Non ero sicuro di aver capito correttamente la domanda, e l'intervistatore ha capito che non sapevo la risposta, e ho interrotto l'intervista.

Cosa avrebbe potuto raggiungere?

+0

Vedere anche la soluzione [Soluzione GotW # 2: Oggetti temporanei] di Herb Sutter (http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/). – jww

risposta

10

In C++, se si dispone di un ciclo for che "copie" oggetti di un tipo definito dall'utente utilizzando un costruttore mossa [...]

Prima di tutto, un costruttore mossa viene utilizzato per move-constructing, che di solito significa che non stai "copiando": puoi can realizzare lo spostamento come copia - in effetti, una classe che è copy-constructible è anche move-constructible - ma allora perché definire esplicitamente un costruttore di move?

[...] fa alcuna differenza se si utilizza ++ i o i ++ come contatore di loop?

Dipende da cosa è i. Se si tratta di un oggetto scalare, come un int, non c'è alcuna differenza.

Se i è una classe di tipo iteratore, d'altra parte, ++i dovrebbe essere più efficiente (su un terreno puramente teorica), perché l'implementazione di operator ++ non dovrà creare una copia del iteratore da restituire prima l'iteratore stesso viene incrementato.

Qui, per esempio, è il modo in stdlibC++ definisce gli operatori di incremento per il tipo iteratore di un std::list:

_Self& 
operator++() 
{ 
    _M_node = _M_node->_M_next; 
    return *this; 
} 

_Self 
operator++(int) 
{ 
    _Self __tmp = *this; 
    _M_node = _M_node->_M_next; 
    return __tmp; 
} 

Come si può vedere, la versione suffisso (quella di accettare un manichino int) ha più lavoro da fare: ha bisogno di creare una copia dell'iteratore originale da refurnare, quindi modificare il puntatore interno dell'iteratore, quindi restituire la copia.

D'altra parte, la versione del prefisso deve solo modificare il puntatore interno e restituire (un riferimento a) stesso.

Tuttavia, si tenga presente che quando si tratta di prestazioni, tutte le ipotesi devono essere sottoposte a backup mediante misurazione. In questo caso, non mi aspetto alcuna differenza sensata tra queste due funzioni.

+1

Ottenuto sulla parte "copia". Sapevo che non avrei dovuto usare quella parola. Quindi questo non ha nulla a che fare con la costruzione di mosse di per sé, giusto? Ha a che fare con ints vs iterators? – Scott

+0

@ Scott: In effetti, questo è il caso. Ho intenzione di espandere la risposta con un esempio di –

+0

Andy se il rh è lvalue quindi spostare sarà pericoloso vero? –

Problemi correlati