2010-10-13 12 views
18

in C++ 11 ora possiamo fare:Il ciclo C++ 11 consente nuove o migliori ottimizzazioni?

void dosomething(std::vector<Thing>& things) 
{ 
    for(Thing& thing : things) 
    { 
     dofoo(thing); 
     wiizzz(thing); 
     tadaa(thing); 
    } 

} 

So che l'aggiunta e l'uso di lambda è zucchero sintattico ma offrire interessanti opportunità di ottimizzazione.

E il ciclo for? È solo lo zucchero sintattico o il compilatore può ottimizzare alcuni casi che non potrebbero o sarebbero troppo difficili da fare con il loop scritto a mano?

+0

'' (Cosa & Cosa: cose) 'in C++ 0x specifica un ordinamento? o potrebbe 'thing' apparire in qualsiasi ordine? – Inverse

+2

Basta prendere l'iteratore dal membro begin() del contenitore specificato (se si tratta di una classe) e iterare fino a raggiungere l'iteratore end(). Quindi è dipendente dall'iterizzatore o dipendente dal contenitore, se lo si desidera. Nel caso di una matrice grezza (o anche di una semantica della matrice?) Passerà da un [0] e terminerà quando raggiungerà una [dimensione]. – Klaim

risposta

21

E 'solo una zucchero sintattico in quanto la norma dice che è equivalente ad un ciclo con iteratori [Modifica: questo significa che non fornisce ulteriori informazioni al compilatore rispetto all'equivalente ciclo for — fine modificare ]. Si può ottenere una migliore performance anche se dal momento che è equivalente a:

for(auto iter = con.begin(), end = con.end(); iter != end; ++iter) 
{ 
    auto& ref = *iter; 
    // ... 
} 

mentre la maggior parte delle persone possono scrivere:

for(auto iter = con.begin(); iter != con.end(); iter++) 
{ 
    // use *iter directly 
    // ... 
} 

che può essere più lenta se il con.end(), ++ iter o * iter non sono banale.

[Edit:

lambda è zucchero sintattico

Non

davvero. A differenza del ciclo, consente al compilatore di catturare direttamente il puntatore di base dello stack frame, per le variabili catturate per riferimento questo salva un indirizzo indiretto per ogni utilizzo, rispetto a un oggetto funzione artigianale. — fine modifica]

+0

Sei sicuro che memorizza nella cache 'end()'? Ciò significa che non puoi mutare la collezione che è semanticamente diversa (per le raccolte che non invalidano gli iteratori all'inserimento/eliminazione ad esempio 'list'). – Motti

+0

Immagino supponga che il contenitore non cambierà. Se lo farà, usare gli algoritmi di stl potrebbe essere un modo migliore. – Klaim

+3

@Motti: lo standard dice esplicitamente che è equivalente al codice precedente (beh, un po 'più complicato perché è formulato in termini di intervalli). Ad ogni modo se il tuo contenitore non invalida gli iteratori, allora end() non è invalido. Allora, qual'è il problema? È possibile modificare il contenitore finché non si interrompe questo codice. – ybungalobill

5

Forse, ma probabilmente no. Elimina la possibile creazione di una variabile indice/contatore che non verrà utilizzata. Quello non è richiesto per un normale ciclo for, ma è molto più probabile che accada solo perché è ciò che alcune persone sono abituate a fare.

Realisticamente, è improbabile che possa fare alcuna differenza anche da quello. Io, almeno, trovo difficile immaginare un team di compilatori così sofisticato da avere anche la minima aspirazione a supportare C++ 0x, che non ha già gestito il punto relativamente banale di rilevare ed eliminare la creazione e l'incremento di un indice di loop che è mai usato.