2014-12-15 7 views
8

Ho appena saputo che il risultato dell'operatore di incremento del prefisso in C++ è un lvalue. Ci sono probabilmente casi in cui questo comportamento aiuta il programmatore ad essere più efficace, ma non potrei pensare a nessuno. Quali sono alcuni usi idiomatici di questo comportamento dell'operatore di incremento del prefisso?Utilizzi pratici del fatto che l'operatore di incremento del prefisso C++ restituisce un lvalue

+0

Per favore, puoi essere più elaborato ... in che contesto stai misurando l'efficienza. – ravi

+0

Vedi anche: http://stackoverflow.com/a/371669/567292 – ecatmur

+0

Grazie. Ho perso questo post nella mia ricerca prima di pubblicare la domanda. Per efficacia intendo codice conciso e chiaro che non sarebbe tale se la funzione non fosse presente nella lingua. – AlwaysLearning

risposta

0
i=9; 
j=10; 
k = ((i)>(j))?(j):(++i); 

Nel caso di cui sopra hanno un uso dell'operatore prefisso incremento come si può c abbiamo prima controllare i> j che sarà falso in questo caso allora stiamo assegnando il valore ++ i ak che darà noi k = 1. Qui in una singola istruzione abbiamo usato due volte ma una volta il valore era 9 e un'altra volta il valore era 10. Se si tenta di ottenere ciò senza l'operatore di prefisso incremento dovremmo usare un'altra variabile temporanea per memorizzare il valore di quindi incremento i per assegnare a k. Senza usare operatore prefisso

i=9; 
j=10; 
Temp=i; 
i=i+1; 
k = ((Temp)>(j))?(j):(i); 

Ancora se si arriva ad una conditin dove temp è greter di j allora avremo il valore dei incrementata anche se noi non usarlo. Usando l'operatore di prefisso il valore di i aumenterà solo se ho meno di j.

+1

L'OP ha chiesto l'uso di ++ i come lvalue. Il tuo primo codice è altrettanto buono in C, dove ++ i è _non_ un lvalue. – gnasher729

4

La modifica da C, dove ++ x è un rvalue a C++, dove ++ x per i tipi built-in è un lvalue è probabilmente perché ci sono molte più applicazioni utili. Ad esempio, è possibile definire una funzione alternativa come

void f (int x); 
void f (int& x); 

e il fatto che ++ x è un Ivalue consente di chiamare f (x ++); in ogni caso. In C, solo il primo caso era legale e funziona perfettamente con un valore. In C++, vuoi un lvalue.

+0

Penso che un caso con 'int f (int x);' e 'int & f (int & x);' sarebbe un po 'più chiaro di un esempio. Restituendo un lvalue quando viene fornito un lvalue, l'lvalue-ness dell'argomento viene preservato attraverso funzione, invece di tutto essere forzato a un valore. Quindi sarebbe sorprendente se l'alimentazione di '++ x' alla funzione chiamasse improvvisamente la versione rvalue della funzione. –

+1

L'esempio più chiaro sarebbe' int const & f (int const &) 'e' int & f (int & ')'. Ma questo porta a 'f (i ++)' chiamando il primo, e 'f (++ i)' il secondo, che è più di un argomento per _not_ making prefisso '++ 'un lvalue. –

6

Il prefisso motivo ++ restituisce un lvalue è ortogonalità; Non ho visto alcun uso per esso che non si qualificherebbe come offuscamento. Ma la domanda è: quali regole si applicano per fare in modo che un'espressione sia un lvalue. In C, la regola di base è che le espressioni che modificano uno dei loro operandi non sono lvalue, ma un certo numero di persone che hanno voluto sostenere cose come:

T& 
someFunction(T& lhs, T const& rhs) 
{ 
    // ... 
    return lhs = rhs; 
} 

Questo funziona per i tipi definiti dall'utente (perché operator= volontà essere membro della funzione ) e alcuni membri volevano supportarlo per i tipi predefiniti come . Quindi la regola base è diventata: se un operatore ha richiesto un operando lvalue , che ha modificato, e, i risultati dell'operatore sono stati l'operando modificato , quindi è un lvalue. (Così, mentre il prefisso ++ è un lvalue, postfix non è, perché i risultati dell'espressione non sono la cambiato operando.)

Personalmente, io non sono sicuro sono d'accordo. Non ho alcun problema con la sostituzione del sopra con:

T& 
someFunction(T& lhs, T const& rhs) 
{ 
    // ... 
    lhs = rhs; 
    return lhs; 
} 

che è come mi piacerebbe scrivere nel mio codice.Ma dato che il primo esempio è legale per i tipi definiti dall'utente (dove operator= restituisce a T&) e che a un certo numero di membri del comitato piace, sembra che sia logico estenderlo ai tipi predefiniti e il conseguente la regola è coerente, anche se nessuno ha mai avuto l'occasione di utilizzare i risultati come prefisso .

EDIT:

Giusto per chiarire: ho chiesto a questa domanda in uno dei incontri (quando stavamo definendo C++ 98), e questo è stato la risposta ho ricevuto (da, se ricordo correttamente, Andy Koenig, il quale ha lavorato con Stroustrup sulle prime implementazioni di C++). Era anche la giustificazione per l'implementazione predefinita di di operator= restituire uno T& anziché uno T const&.

Problemi correlati