Question

J'ai l'impression que ces deux commandes ont la même finalité, à savoir l'incrémentation de X de 1, mais que cette dernière est probablement plus efficace.

Si cela n’est pas correct, veuillez expliquer la différence.

S'il est correct, pourquoi ce dernier devrait-il être plus efficace? Ne devraient-ils pas tous les deux compiler sur le même IL?

Merci.

Était-ce utile?

La solution

A partir de la bibliothèque MSDN pour + = :

.
  

Utiliser cet opérateur revient presque à spécifier result = result + expression, sauf que le résultat n'est évalué qu'une fois.

Ils ne sont donc pas identiques et c’est pourquoi x + = 1 sera plus efficace.

Mise à jour: je viens de constater que le lien de ma bibliothèque MSDN était vers la page JScript au lieu de page VB , qui ne contient pas le même guillemet.

Par conséquent, lors de recherches et de tests supplémentaires, cette réponse ne s'applique pas à VB.NET. J'avais tort. Voici un exemple d'application de la console:

Module Module1

Sub Main()
    Dim x = 0
    Console.WriteLine(PlusEqual1(x))
    Console.WriteLine(Add1(x))
    Console.WriteLine(PlusEqual2(x))
    Console.WriteLine(Add2(x))
    Console.ReadLine()
End Sub

Public Function PlusEqual1(ByVal x As Integer) As Integer
    x += 1
    Return x
End Function

Public Function Add1(ByVal x As Integer) As Integer
    x = x + 1
    Return x
End Function

Public Function PlusEqual2(ByVal x As Integer) As Integer
    x += 2
    Return x
End Function

Public Function Add2(ByVal x As Integer) As Integer
    x = x + 2
    Return x
End Function

End Module

IL pour les deux PlusEqual1 et Add1 sont en effet identiques:

.method public static int32 Add1(int32 x) cil managed
{
.maxstack 2
.locals init (
    [0] int32 Add1)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.1 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}

Les IL pour PlusEqual2 et Add2 sont presque identiques:

.method public static int32 Add2(int32 x) cil managed
{ 
.maxstack 2
.locals init (
    [0] int32 Add2)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.2 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}

Autres conseils

J'ai écrit une application console simple:

static void Main(string[] args)
{
    int i = 0;
    i += 1;
    i = i + 1;
    Console.WriteLine(i);
}

Je l'ai démonté à l'aide de Reflector et voici ce que j'ai obtenu:

private static void Main(string[] args)
{
    int i = 0;
    i++;
    i++;
    Console.WriteLine(i);
}

Ce sont les mêmes.

ils compilent à la même chose, la seconde est tout simplement plus facile à taper.

IMPORTANT:

Les réponses spécifiant l'évaluation sont certainement correctes en termes de ce qu'un + = fait, dans les langages généraux. Mais dans VB.NET, je suppose que X spécifié dans l'OP est une variable ou une propriété.

Ils vont probablement compiler sur le même IL.

UPDATE (pour répondre à la controverse probable):

VB.NET est une spécification d’un langage de programmation. Tout compilateur conforme à ce qui est défini dans la spécification peut être une implémentation de VB.NET. Si vous éditez le code source du compilateur MS VB.NET pour générer un code de merde pour le cas X + = 1 , vous serez toujours conforme à la spécification VB.NET (car il ne dit rien à propos de comment cela va fonctionner. Cela indique simplement que l'effet sera exactement le même, ce qui rend logique de générer le même code, en effet).

Bien que le compilateur soit très probable (et je pense que c'est le cas), il génère le même code pour les deux, mais c'est un logiciel assez complexe. Heck, vous ne pouvez même pas garantir qu'un compilateur génère exactement le même code lorsque le même code est compilé deux fois!

Ce que vous pouvez être sûr à 100% de dire (à moins que vous ne connaissiez intimement le code source du compilateur) est qu'un bon compilateur devrait générer le même code, en termes de performances , ce qui pourrait ou pourrait ne pas être le code exact même .

Tant de spéculations! Même la conclusion concernant le réflecteur n’est pas forcément vraie, car elle permet d’optimiser en désassemblant.

Alors, pourquoi aucun de vous ne se penche sur le code IL? Consultez le programme C # suivant:

static void Main(string[] args)
{
    int x = 2;
    int y = 3;
    x += 1;
    y = y + 1;
    Console.WriteLine(x);
    Console.WriteLine(y);
}

Cet extrait de code est compilé en:

.method private hidebysig static void Main (string [] args) cil géré
{
.entrypoint
// taille du code 25 (0x19)
.maxstack 2
.locals init ([0] int32 x,
) [1] int32 y)
// certaines commandes omises ici

IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: ajouter
IL_0007: stloc.0

IL_0008: ldloc.1
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stloc.1

// certaines commandes omises ici
}

Comme vous pouvez le constater, c’est en fait absolument la même chose. Et pourquoi c'est ça? Parce que le but de l'IL est de dire quoi faire, pas comment. L’optimisation sera un travail du compilateur JIT. Au fait, c'est pareil en VB.Net

Sur x86, si x est dans le registre eax, ils aboutiront tous les deux à un résultat similaire à

inc eax;

Donc, vous avez raison, après une étape de compilation, le IL sera le même.

Il existe toute une catégorie de questions de ce type auxquelles il est possible de répondre par "faites confiance à votre optimiseur".

Le mythe célèbre est que
x ++;
est moins efficace que
++ x;
car il doit stocker une valeur temporaire. Si vous n'utilisez jamais la valeur temporaire, l'optimiseur supprimera ce magasin.

  1. Oui, ils se comportent de la même manière.
  2. Non, ils sont probablement tout aussi efficaces. Les optimiseurs sont bons dans ce genre de chose. Si vous souhaitez vérifier, écrivez le code optimisé et visualisez-le dans le réflecteur.

L'optimiseur produit probablement le même résultat, si x est un type simple comme int ou float.

Si vous utilisiez un autre langage (connaissance limitée de VB ici, pouvez-vous surcharger + =?) où x pourrait être un gros objet qui klaxonne, l'ancien crée et la copie supplémentaire, qui peut représenter des centaines de mégas. Ce dernier ne le fait pas.

sont les mêmes.

x=x+1 

est mathématique vu une contradiction alors que

x+=1

n'est pas et est léger à taper.

Ils peuvent être les mêmes dans VB; ils ne sont pas nécessairement les mêmes en C (d'où vient l'opérateur).

En C ++, le type de données est x et la définition des opérateurs. Si x est une instance d'une classe, vous pouvez obtenir des résultats complètement différents.

Vous pouvez également résoudre le problème en précisant que x est un entier ou autre.

Je pensais que les différences étaient dues aux cycles d’horloge supplémentaires utilisés pour les références en mémoire, mais j’ai eu tort! ne peux pas comprendre cette chose moi-même

instruction type        example                      cycles

============================================ =======================

ADD reg,reg             add ax,bx                       1
ADD mem,reg             add total, cx                   3
ADD reg,mem             add cx,incr                     2
ADD reg,immed           add bx,6                        1
ADD mem,immed           add pointers[bx][si],6          3
ADD accum,immed         add ax,10                       1

INC reg                 inc bx                          1
INC mem                 inc vpage                       3

MOV reg,reg             mov bp,sp                       1
MOV mem,reg             mov array[di],bx                1
MOV reg,mem             mov bx,pointer                  1
MOV mem,immed           mov [bx],15                     1
MOV reg,immed           mov cx,256                      1
MOV mem,accum           mov total,ax                    1
MOV accum,mem           mov al,string                   1
MOV segreg,reg16        mov ds,ax                       2, 3
MOV segreg,mem16        mov es,psp                      2, 3
MOV reg16,segreg        mov ax,ds                       1
MOV mem16,segreg        mov stack_save,ss               1
MOV reg32,controlreg    mov eax,cr0                     22
                        mov eax,cr2                     12
                        mov eax,cr3                     21, 46
                        mov eax,cr4                     14
MOV controlreg,reg32    mov cr0,eax                     4
MOV reg32,debugreg      mov edx,dr0                     DR0-DR3,DR6,DR7=11;
                                                        DR4,DR5=12 
MOV debugreg,reg32      mov dr0,ecx                     DR0-DR3,DR6,DR7=11;
                                                        DR4,DR5=12 

source: http://turkish_rational.tripod.com/trdos/pentium.txt

les instructions peuvent être traduites comme suit:

;for i = i+1   ; cycles
mov  ax,   [i]  ; 1
add  ax,   1    ; 1
mov  [i],  ax   ; 1

;for i += 1
; dunno the syntax of instruction. it should be the pointers one :S     

;for i++
inc  i          ; 3
;or
mov  ax,   [i]  ; 1
inc  ax         ; 1
mov  [i],  ax   ; 1

;for ++i
mov  ax,   [i]  ; 1
;do  stuff      ; matters not
inc  ax         ; 1
mov  [i],  ax   ; 1

Tous se révèlent être identique: S c'est juste quelques données qui peuvent être utiles. commentez s'il vous plaît!

Il est intéressant de noter que + =, - =, * = etc. font un casting implicite.

int i = 0;
i = i + 5.5; // doesn't compile.
i += 5.5; // compiles.

Au moment de l'exécution (au moins avec PERL), il n'y a pas de différence. x + = 1 est environ 0,5 seconde plus rapide à taper que x = x + 1 si

Il n'y a pas de différence d'efficacité des programmes; il suffit de taper l'efficacité.

Au début des années 1980, l’une des optimisations vraiment intéressantes du compilateur Lattice C était que "x = x + 1;", "x + = 1;" et " x ++; " tous ont produit exactement le même code machine. S'ils y parviennent, un compilateur écrit au cours de ce millénaire devrait pouvoir le faire.

Si x est une variable scalaire entière simple, elles doivent être identiques.

Si x est une expression de grande taille, avec éventuellement des effets secondaires, + = 1 et ++ devraient être deux fois plus rapides.

De nombreuses personnes se concentrent sur ce type d’optimisation de bas niveau, comme si c’était vraiment l’optimisation. Je suppose que vous savez que le sujet est beaucoup plus vaste.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top