2010-06-18 8 views
10

En C++ Je comprends que (++i) doit renvoyer une référence à i parce que la nécessité de concaténation des opérateurs, mais ce que je ne peux pas comprendre est:Différence entre (++ i) et (i ++)

Pourquoi (i++) devrait renvoyer i par valeur?

Quelqu'un peut-il clarifier s'il vous plaît.

+1

Sauf si vous parlez d'une langue spécifique, ++ je renvoie toujours la valeur, pas une référence. – HoLyVieR

+0

@all: Je suis à peu près sûr que c'est bien comme langue-agnostique. Y a-t-il un langage qui pourrait renvoyer «i ++» par référence? Il vaut mieux renvoyer une nouvelle valeur dans l'implémentation de n'importe quelle langue. – Stephen

+0

Basé sur le contexte de la question, je suppose qu'il parle de surcharger l'opérateur ++ en C++. Une clarification de la question serait utile. – 5ound

Répondre

18

++i peut être écrit comme

prefix_inc (this) { 
    increase this by 1 
    return this 
} 

Depuis le vrai i est retourné, nous pouvons prendre référence de celui-ci. Cependant, i++ ressemble

postfix_inc (this) { 
    set old_this = copy of this 
    increase this by 1 
    return old_this 
} 

comme old_this est juste une variable locale, la référence de celui-ci est inutile après i++ est terminé. Donc, logiquement, il devrait retourner une valeur.

27

i++ retourne une valeur parce qu'elle est renvoie la ancienne valeur de i, tandis que i augmente par 1.

Une implémentation de base de ce serait:

int i++() { 
    int old = i; 
    i = i + 1; 
    return old; 
} 

Ainsi, si elle retourne une référence, il serait la mauvaise valeur ... puisque la valeur de i a été incrémentée!

+2

En outre, il ne peut pas renvoyer une référence à 'old', car vous ne pouvez pas renvoyer une référence (ou un pointeur) à un fichier temporaire. –

4

Soit foo être une fonction. foo(i++) appelle foo(i) avec l'ancienne valeur de i et incrémente i, d'où la nécessité de générer une copie temporaire. foo(++i) incrémente i, puis appelle foo avec la valeur incrémentée, donc pour de meilleures performances, nous pouvons réutiliser la même variable, pas besoin d'avoir une copie temporaire.

+4

'foo (i ++)' incrémente 'i' et _then_ appelle' foo' avec la valeur originale de 'i'. Il y a un point de séquence entre l'évaluation du paramètre (avec son effet secondaire) et l'appel de la fonction. –

-4

Si vous êtes déjà dans un scénario où cela importe, vous le faites mal.

+5

Si vous devez surcharger cet opérateur, il est important que vous compreniez comment ils fonctionnent. – chustar

+0

Je ne voudrais pas infliger ++ i vs i ++ à toute personne qui devait utiliser ma classe. – Puppy

1
int i = 0; 
Console.Writeline(i++); // Output 0, after that, i will be 1 


int x = 0; 
Console.Writeline(++x); // Output 1 

Note: le code est en C#

2

i ++ Cela renvoie la valeur de la i avant qu'il ne soit incrémenté. Donc, l'idée est que si vous voulez utiliser i dans une fonction, puis incrémenter la valeur après l'avoir utilisée, vous pouvez le faire en une seule étape. À titre d'exemple, voici comment je surcharger cet opérateur pour les entiers.

Integer Integer::operator++() 
{ 
    Integer returnValue = *this; 
    this->increment(); 
    return returnValue; 
} 

Il incrémente la valeur, puis retourne ce qu'il utilisé être. Il ne renvoie pas non plus de référence, car renvoyer une référence serait différent de ce qui a été passé à l'origine, ce qui casse la cascade.

++ i Cela incrémente la valeur de i et renvoie la nouvelle valeur. Vous pouvez donc utiliser ceci dans une situation où vous voulez incrémenter i et ensuite utiliser la nouvelle valeur dans votre fonction.La valeur renvoyée est donc la valeur incrémentée de i.

0

Lorsque le préfixe ++i renvoie la valeur incrémentée et le suffixe i++ renvoie l'ancienne valeur et l'incrémente ensuite, la sélection de l'opérateur est significative si vous tenez compte des cycles du processeur. incrément Prefix est plus rapide ;-)

+0

Pourquoi l'incrémentation du préfixe est plus rapide ??? –

+0

Les compilateurs simplistes peuvent créer une variable temporaire pour stocker la valeur intermédiaire. Cela ne coûte rien pour les types standards comme 'int'mais par exemple. objets, il peut être coûteux. Cela importe si votre application est liée à l'UC. Voir http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.15 – puudeli

0

5 cents:

En conséquence de i++ faire une copie, il est plus lent pour les variables non-POD (à savoir itérateurs). Vous devriez utiliser ++i partout où c'est possible.

Personnellement, j'utilise toujours for(...;...;++i) au lieu de for(...;...;i++), bien que compiller devrait optimiser cela.