web-dev-qa-db-fra.com

Quelle est la différence entre les opérateurs "++" et "+ = 1"?

Dans une boucle en C++, je rencontre généralement des situations pour utiliser ++ ou +=1, mais je ne peux pas faire de différence. Par exemple, si j'ai un entier

int num = 0;

puis en boucle je fais:

num ++;

ou

num += 1;

ils augmentent tous les deux la valeur de num, mais quelle est leur différence? Je doute num++ pourrait fonctionner plus rapidement que num+=1, mais comment? Cette différence est-elle suffisamment subtile pour être ignorée?

42
E_learner

num += 1 est plutôt équivalent à ++num.

Toutes ces expressions (num += 1, num++ et ++num) incrémente la valeur de num d'une unité, mais la valeur de num++ est la valeur num avait avant elle a été incrémentée.

Illustration:

int a = 0;
int b = a++; // now b == 0 and a == 1
int c = ++a; // now c == 2 and a == 2
int d = (a += 1); // now d == 3 and a == 3

Utilisez ce qui vous plaît. Je préfère ++num à num += 1 car il est plus court.

81
Alexandre C.

préfixe et postfix les opérations sont des candidats parfaits pour les questions d'examen.

a = 0;
b = a++;  // use the value and then increment --> a: 1, b: 0

a = 0;
b = ++a;  // increment and then use the value --> a: 1, b: 1

+= opération et sa sœur -= sont des solutions plus générales destinées principalement à être utilisées avec des nombres différents. On pourrait même dire qu'ils sont redondants lorsqu'ils sont utilisés avec 1. Lorsqu'il est utilisé avec 1 ils agissent principalement comme une opération préfixe. En fait, sur ma machine, ils produisent le même code machine. Vous pouvez essayer cela en utilisant un exemple de programme tel que:

void foo() {
    int a, b;
    a = 0;

    // use one of these four at a time
    b = a++;          // first case (different)
    b = ++a;          // second case
    b = (a += 1);     // third case
    b = (a = a + 1);  // fourth case
}

int main() {
    foo();
    return 0;
}

et démontage dans gdb ce qui donnerait:

premier cas (a++) (différent)

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    mov    -0x8(%rbp),%eax
   0x00000000004004c2 <+14>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c5 <+17>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq
End of assembler dump.

deuxième cas (++a)

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c3 <+15>:    mov    -0x8(%rbp),%eax
   0x00000000004004c6 <+18>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq   
End of assembler dump.

troisième cas (a += 1)

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c3 <+15>:    mov    -0x8(%rbp),%eax
   0x00000000004004c6 <+18>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq   
End of assembler dump.

quatrième cas (a = a + 1)

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c3 <+15>:    mov    -0x8(%rbp),%eax
   0x00000000004004c6 <+18>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq   
End of assembler dump.

Comme vous pouvez le voir, ils produisent le même code machine même sans optimisation du compilateur activée sauf le premier cas qui a addl après movs. Cela signifie que vous devez utiliser ce que vous voulez en tant qu'utilisateur et laisser les gars du compilateur faire le reste.

Enfin, notez que les opérateurs cousins ​​*= et /= n'ont pas de contreparties postfix et préfixe.

21
none

Le ++ opérateurs de préfixe ou de suffixe changer la valeur de la variable.

int a = 0;
int b = a++; // b is equal to 0, a is equal to 1

Ou préfixe:

int a = 0;
int b = ++a; // b = 1, a = 1

S'ils sont utilisés comme ça, ils sont les mêmes:

int a = 0;
++a; // 1
a++; // 2
a += 1; // 3
10
dreamzor

Les deux opérateurs augmentent la valeur de n de 1. La différence entre eux existe lorsque vous utilisez les opérateurs avec l'opérateur d'affectation.

Par exemple:

Premier cas - Opérateur post-incrément

int n=5;
int new_var;

new_var=n++;

print("%d",new_var);

Sortie = 5

Deuxième cas

int n=5;
n+=1;
new_var=n;
print("%d",new_var);

Sortie = 6

Ceci est très similaire à ce que l'opérateur de pré-incrémentation entraînerait.

Deuxième cas utilisant l'opérateur de pré-incrémentation

int n=5;

new_var=++n;
print("%d",new_var);

Sortie = 6

6
Desert Ice

Ils sont généralement les mêmes et il n'y a aucune signification pour clarifier la différence entre eux. Mais la mise en œuvre de ces deux déclarations est en fait différente. Par exemple, un + = 1 de compilation à assember est
ajoutez a, 1
et a ++ ou ++ a est
inc a
Il peut y avoir une légère différence d'efficacité car il s'agit de deux processeurs différents.

2
bigfish

Ces deux opérateurs peuvent sembler similaires, mais ils sont assez différents.

Pour les types primitifs (pointeurs, entiers, etc.), ils incrémentent tous les deux la valeur d'un. Mais, pour les classes C++, ils appellent différents opérateurs (operator+= contre. operator++); en effet, pour certaines classes, comme list<T>::iterator, i += 1 ne fonctionne pas et i++ doit être utilisé.

De plus, ils produisent des valeurs différentes. i += 1 produit i après incrémentation (comme un pré-incrément), tandis que i++ produit i avant d'incrémenter. Ainsi,

int a = 0, b = 0;
cout << (a+=1) << " " << b++ << endl;

imprime 1 0. Car i += 1 équivaut à un pré-incrément, dans certains cas, i += 1 peut résulter

Ainsi, bien qu'ils soient les mêmes pour incrémenter des variables, il faut savoir qu'ils ne sont pas des substituts parfaits dans toutes les conditions.

2
nneonneo

Certains d'entre vous approchent de la différence, mais il faut le dire très clairement:

ILS SONT DES OPÉRATEURS TRÈS DIFFÉRENTS.

Les opérateurs pré-incrément et post-incrément sont conçus pour être utilisés DANS LES EXPRESSIONS pour modifier la valeur de la variable AVANT ou APRÈS que la valeur de la variable soit utilisée dans l'expression qui l'entoure. Lorsque vous utilisez l'opérateur de post-incrémentation, la valeur OLD de la variable est utilisée pour évaluer l'expression englobante et ce n'est qu'après cela que la variable est incrémentée.

Par exemple:

i = 10;
j = i++;  // This causes j to be 10 while i becomes 11.

C'est pourquoi il est appelé l'opérateur de post-incrémentation. La variable est incrémentée POST (APRÈS) sa valeur est utilisée dans la plus grande expression (ici une expression d'affectation).

Cependant, si vous le faites:

i = 10;
j = ++i; // Now both i and j will be 11 because the increment
         // of i occurs PRE (BEFORE) its value is used in the greater expression.
2
Tom Wetmore

Je suis surpris que personne ne mentionne qu'au moins pour les anciens compilateurs/ordinateurs (essentiellement quand C est né et une décennie ou deux après) += 1 sera considérablement plus lent que ++. ++ est un incrément pour lequel le CPU a probablement une seule instruction. += 1 nécessite de charger la valeur 1 dans un registre (probablement d'en sauvegarder la valeur ... quelque part) et d'appeler pour un ajout. Je ne peux pas dire si les compilateurs actuels optimisent cela, mais je pense que oui.

1
chx

Je suis nouveau sur Stackoverflow mais voici ma valeur de 2 pence.

Si la question concerne + = et non + = 1. La déclaration publiée était;

Je rencontre généralement des situations pour utiliser ++ ou + = 1, mais je ne peux pas faire de différence.

Je pense que le 1 aurait pu facilement être un autre nombre ou peut-être mieux écrit comme + =?

En termes de résultat, il n'y a pas de différence (en utilisant les valeurs des affiches). Les deux vont s'incrémenter de un, cependant, ++ n'augmentera que de 1 tandis que + = incrémentera de la valeur spécifiée par le codeur, dans l'exemple d'Ederman, cela se trouve être 1. Par exemple:

// Example 1:
num = 0;
num = ++;
// the result of num will be 1

// Example 2:
num = 0;
num = += 1;
// the result of num will be 1 the same as example 1

// Example 3:
num = 0;
num = += 2;
// the result of num will be 2.

// Example 4:
num = 0;
num = ++ 2;
// this would not compile as ++ will not except any value for the increment step it is assumed
// you will always want to increment by the value of 1

Donc, si vous voulez seulement incrémenter une valeur de 1, j'utiliserais ++ mais si vous avez besoin d'incrémenter de plus le 1, utilisez + =

J'espère que c'est utile.

1
Kevin Morrissey

++ est utilisé pour incrémenter la valeur de 1, tandis qu'en utilisant + = vous pouvez incrémenter d'un autre montant.

0
Alfa3eta