Różnica między przyrostem wstępnym a przyrostowym w pętli?


303

Czy jest jakaś różnica w ++ii i++w forpętli? Czy to po prostu składnia?



18
Dziwi mnie, jak wiele odpowiedzi całkowicie pomijało sedno pytania.
Graeme Perrow

3
Być może powinniśmy się dziwić, że nikt nie zredagował pytania, aby było bardziej jasne :)
Jon B

2
To pytanie może dotyczyć C, Java, C ++, PHP, C #, JavaScript, JScript, Objective C: en.wikipedia.org/wiki/Category:C_programming_language_family
Chris S

1
Dobra odpowiedź opublikowana tutaj: stackoverflow.com/a/4706225/214296
Jim Fell

Odpowiedzi:


233

++ jest znany jako postfix.

dodać 1 do a, zwraca starą wartość.

++ a jest znany jako przedrostek.

dodać 1 do a, zwraca nową wartość.

DO#:

string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
    Console.WriteLine(++i);
}
Console.WriteLine("");

i = 0;
foreach (string item in items)
{
    Console.WriteLine(i++);
}

Wynik:

1
2
3
4

0
1
2
3

foreacha whilepętle zależą od używanego typu przyrostu. Z pętlami jak poniżej nie ma znaczenia, ponieważ nie używasz wartości zwracanej przez i:

for (int i = 0; i < 5; i++) { Console.Write(i);}
Console.WriteLine("");
for (int i = 0; i < 5; ++i) { Console.Write(i); }

0 1 2 3 4
0 1 2 3 4

Jeśli zastosowana zostanie wartość oszacowana, wówczas rodzaj przyrostu będzie znaczący:

int n = 0;
for (int i = 0; n < 5; n = i++) { }

4
To nie jest to, o co prosił użytkownik.
Dimitri,

223

Pre-inkrement ++ i inkrementuje wartość i i ocenia do nowej wartości inkrementowanej.

int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );

Post-inkrementacja i ++ inkrementuje wartość i i ocenia do pierwotnej nierekrementowanej wartości.

int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );

W C ++ przyrost jest zwykle preferowany tam, gdzie możesz użyć jednego z nich.

Wynika to z faktu, że jeśli użyjesz funkcji przyrostowej, kompilator może wymagać wygenerowania kodu, który tworzy dodatkową zmienną tymczasową. Wynika to z faktu, że zarówno poprzednia, jak i nowa wartość inkrementowanej zmiennej muszą być gdzieś przechowywane, ponieważ mogą być potrzebne w innym miejscu w ocenianym wyrażeniu.

Tak więc przynajmniej w C ++ może występować różnica w wydajności, która poprowadzi twój wybór, którego użyć.

Jest to głównie problem tylko wtedy, gdy inkrementowana zmienna jest typem zdefiniowanym przez użytkownika z przesłoniętym operatorem ++. W przypadku typów pierwotnych (int itp.) Nie ma różnicy w wydajności. Warto jednak pozostać przy operatorze wstępnego zwiększania jako wskazówkę, chyba że operator po zwiększeniu jest zdecydowanie wymagany.

Tutaj jest trochę więcej dyskusji:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm

W C ++, jeśli używasz STL, możesz używać pętli z iteratorami. Te mają głównie przesłonięte operatory ++, więc trzymanie się wstępnego przyrostu jest dobrym pomysłem. Kompilatory cały czas stają się inteligentniejsze, a nowsze mogą być w stanie przeprowadzić optymalizacje, co oznacza, że ​​nie ma różnicy w wydajności - szczególnie jeśli typ inkrementowany jest zdefiniowany w pliku nagłówkowym (jak często są implementacje STL), dzięki czemu kompilator może zobaczyć, jak metoda jest zaimplementowana, a następnie może wiedzieć, jakie optymalizacje są bezpieczne do wykonania. Mimo to prawdopodobnie nadal warto trzymać się wstępnego przyrostu, ponieważ pętle są wykonywane wiele razy, a to oznacza, że ​​niewielka kara za wydajność może wkrótce zostać zwiększona.


W innych językach, takich jak C #, w których operator ++ nie może być przeciążony, nie ma różnicy w wydajności. Używane w pętli do przesuwania zmiennej pętli, operatory przyrostowe przed i po są równoważne.

Poprawka: przeciążenie ++ w języku C # jest dozwolone. Wydaje się jednak, że w porównaniu do C ++ w języku c # nie można przeciążać wersji wstępnej i końcowej niezależnie. Zakładam więc, że jeśli wynik wywołania ++ w C # nie zostanie przypisany do zmiennej lub użyty jako część złożonego wyrażenia, to kompilator zredukuje wersje przed i po ++ do kodu, który działa równorzędnie.


102
Czy nie byłoby wspaniale, gdyby nazwa C ++ została nazwana ++ C, co oznacza, że ​​można za jej pomocą napisać dobrze zoptymalizowany kod?
Naveen

9
Czy współczesne kompilatory nie powinny być w stanie zoptymalizować tego, skoro wynikowa wartość i tak oczywiście zostanie zniszczona?
che

6
@che - robią to, gdy jest to prosty typ, jednak klasy, które przeciążają operator ++ (takie jak iteratory) to inna historia.
Ferruccio

7
@che: To dobre pytanie. Powód, dla którego kompilatory C ++ nie zastępują „CustomType ++;” z „++ CustomType;” to dlatego, że nie ma gwarancji, że obie funkcje zdefiniowane przez użytkownika mają taki sam efekt. POWINNY ... ale nie ma gwarancji.
Drew Dormann

2
@ michael.bartnett: Dobrze, przeciążenie ++ w C # wydaje się być dostępne. Wydaje się jednak, że w porównaniu do c ++, w języku c # nie można przeciążać wersji wstępnej i końcowej niezależnie. Zakładam więc, że jeśli wynik wywołania ++ w C # nie zostanie przypisany do zmiennej lub użyty jako część złożonego wyrażenia, to kompilator zredukuje wersje przed i po ++ do kodu, który działa równorzędnie.
Scott Langham,

83

W języku C # nie ma różnicy, gdy jest używany w pętli for .

for (int i = 0; i < 10; i++) { Console.WriteLine(i); }

wypisuje to samo co

for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }

Jak zauważyli inni, kiedy używa się ogólnie i ++ i ++, mam subtelną, ale znaczącą różnicę:

int i = 0;
Console.WriteLine(i++);   // Prints 0
int j = 0;
Console.WriteLine(++j);   // Prints 1

i ++ odczytuje wartość i, a następnie ją zwiększa.

++ i zwiększa wartość i, a następnie ją odczytuje.


Podsumowując: ta sama semantyka po / przed przyrostem jak w C ++.
xtofl

@xtofl - nie jesteś pewien, o co ci chodzi? Właśnie przypadkiem wybrałem c # dla mojego przykładu.
Jon B

3
Nie sądzę, aby pierwszy punkt był istotny. W pętli for (c # lub nie) część przyrostowa jest zawsze wykonywana po treści pętli. Po uruchomieniu zmienna jest modyfikowana niezależnie od tego, czy użyto przyrostu wstępnego, czy wstępnego.
MatthieuP

9
@ MatthieuP - czytam pytanie jako „czy ma znaczenie, czy używasz i ++ czy ++ i w pętli for”. Odpowiedź brzmi „nie, nie”.
Jon B

1
@JonB Kolejność operacji w odpowiedzi nie jest dokładnie poprawna. Zarówno ++ii i++wykonaj te same operacje w tej samej kolejności: utwórz tymczasową kopię i; zwiększyć wartość temp, aby uzyskać nową wartość (nie zastępować temp); zapisz nową wartość w i; teraz, jeśli ++iwynik jest zwracany, to nowa wartość; jeśli i++wynik jest zwracany, to kopia tymczasowa. Bardziej szczegółowa odpowiedź tutaj: stackoverflow.com/a/3346729/3330348
PiotrWolkowski

51

Pytanie brzmi:

Czy istnieje różnica w ++ i i ++ w pętli for?

Odpowiedź brzmi: nie .

Dlaczego każda inna odpowiedź musi zawierać szczegółowe objaśnienia dotyczące inkrementacji przed i po, gdy nie jest to nawet zadawane?

Ta pętla for:

for (int i = 0; // Initialization
     i < 5;     // Condition
     i++)       // Increment
{
   Output(i);
}

Przetłumaczyłbym na ten kod bez użycia pętli:

int i = 0; // Initialization

loopStart:
if (i < 5) // Condition
{
   Output(i);

   i++ or ++i; // Increment

   goto loopStart;
}

Czy ma to teraz znaczenie, czy umieścisz tutaj, i++czy ++ijako przyrost? Nie, nie dlatego, że wartość zwracana operacji przyrostowej jest nieznaczna. ibędzie zwiększany PO wykonaniu kodu znajdującego się w treści pętli for.


2
Jest to dosłownie pierwsza odpowiedź, która trafia w sedno. Dzięki.
Yassir

1
To nie jest najlepsza odpowiedź, ponieważ jeśli pętla for zwiększa obiekt złożony (coś innego niż int!), Implementacja ++ x może być szybsza niż x ++ ... (patrz herbutter.com/2013/05/13/gotw -2-solution-tymczasowe-obiekty )
JCx

30

Ponieważ pytasz o różnicę w pętli, myślę, że masz na myśli

for(int i=0; i<10; i++) 
    ...;

W takim przypadku nie ma różnicy w większości języków: Pętla zachowuje się tak samo, niezależnie od tego, czy piszesz i++i ++i. W C ++ możesz pisać własne wersje operatorów ++ i możesz zdefiniować dla nich osobne znaczenia, jeśli ijest to typ zdefiniowany przez użytkownika (na przykład twoja własna klasa).

Powodem, dla którego nie ma to znaczenia powyżej, jest to, że nie używasz wartości i++. Inną rzeczą jest, kiedy to robisz

for(int i=0, a = 0; i<10; a = i++) 
    ...;

Teraz jest różnica, ponieważ, jak podkreślają inni, i++oznacza przyrost, ale oszacowanie do poprzedniej wartości , ale ++ioznacza przyrost, ale oszacowanie doi (w ten sposób oszacowałoby do nowej wartości). W powyższym przypadku aprzypisana jest poprzednia wartość i, natomiast i jest zwiększane.


3
W C ++ nie zawsze jest możliwe, aby kompilator uniknął tworzenia wartości tymczasowych, dlatego preferowana jest forma wstępnego przyrostu.
David Thornley

jak piszę, jeśli masz i typu zdefiniowanego przez użytkownika, mogą mieć inną semantykę. ale jeśli użyjesz i typu pierwotnego, nie robi to różnicy dla pierwszej pętli. ponieważ jest to pytanie agnostyczne związane z językiem, pomyślałem, że nie będę pisał zbyt wiele o specyficznych dla C ++ rzeczach.
Johannes Schaub - litb

15

Jak pokazuje ten kod (patrz nieszyfrowany MSIL w komentarzach), kompilator C # 3 nie wprowadza rozróżnienia między i ++ i ++ i w pętli for. Gdyby wziąć wartość i ++ lub ++ i, na pewno byłaby różnica (ta została skompilowana w Visutal Studio 2008 / Release Build):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PreOrPostIncrement
{
    class Program
    {
        static int SomethingToIncrement;

        static void Main(string[] args)
        {
            PreIncrement(1000);
            PostIncrement(1000);
            Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
        }

        static void PreIncrement(int count)
        {
            /*
            .method private hidebysig static void  PreIncrement(int32 count) cil managed
            {
              // Code size       25 (0x19)
              .maxstack  2
              .locals init ([0] int32 i)
              IL_0000:  ldc.i4.0
              IL_0001:  stloc.0
              IL_0002:  br.s       IL_0014
              IL_0004:  ldsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
              IL_0009:  ldc.i4.1
              IL_000a:  add
              IL_000b:  stsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
              IL_0010:  ldloc.0
              IL_0011:  ldc.i4.1
              IL_0012:  add
              IL_0013:  stloc.0
              IL_0014:  ldloc.0
              IL_0015:  ldarg.0
              IL_0016:  blt.s      IL_0004
              IL_0018:  ret
            } // end of method Program::PreIncrement             
             */
            for (int i = 0; i < count; ++i)
            {
                ++SomethingToIncrement;
            }
        }

        static void PostIncrement(int count)
        {
            /*
                .method private hidebysig static void  PostIncrement(int32 count) cil managed
                {
                  // Code size       25 (0x19)
                  .maxstack  2
                  .locals init ([0] int32 i)
                  IL_0000:  ldc.i4.0
                  IL_0001:  stloc.0
                  IL_0002:  br.s       IL_0014
                  IL_0004:  ldsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
                  IL_0009:  ldc.i4.1
                  IL_000a:  add
                  IL_000b:  stsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
                  IL_0010:  ldloc.0
                  IL_0011:  ldc.i4.1
                  IL_0012:  add
                  IL_0013:  stloc.0
                  IL_0014:  ldloc.0
                  IL_0015:  ldarg.0
                  IL_0016:  blt.s      IL_0004
                  IL_0018:  ret
                } // end of method Program::PostIncrement
             */
            for (int i = 0; i < count; i++)
            {
                SomethingToIncrement++;
            }
        }
    }
}

14

Jeden (++ i) to wzrost wstępny, jeden (i ++) to wzrost wstępny. Różnica polega na tym, jaka wartość jest natychmiast zwracana z wyrażenia.

// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1

Edycja: Woops, całkowicie zignorowałem pętlę rzeczy. Nie ma żadnej rzeczywistej różnicy w przypadku pętli, gdy jest to część „krokowa” (dla (...; ...;)), ale może wejść w grę w innych przypadkach.


7

Nie ma różnicy, jeśli nie używasz wartości po inkrementacji w pętli.

for (int i = 0; i < 4; ++i){
cout<<i;       
}
for (int i = 0; i < 4; i++){
cout<<i;       
}

Obie pętle wydrukują 0123.

Ale różnica pojawia się, gdy używasz wartości po inkrementacji / dekrementacji w swojej pętli, jak poniżej:

Pętla przed przyrostem:

for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";       
cout<<k<<" "; 
}

Wyjście: 0 0 1 1 2 2 3 3

Pętla przyrostowa:

for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";       
cout<<k<<" "; 
}

Wyjście: 0 0 1 0 2 1 3 2

Mam nadzieję, że różnica jest wyraźna poprzez porównanie wyników. Należy zwrócić uwagę na to, że inkrementacja / dekrementacja jest zawsze wykonywana na końcu pętli for, a zatem wyniki można wyjaśnić.


7

Oto przykład Java, a kod bajtowy, post- i preIncrement nie pokazują żadnej różnicy w kodzie bajtowym:

public class PreOrPostIncrement {

    static int somethingToIncrement = 0;

    public static void main(String[] args) {
        final int rounds = 1000;
        postIncrement(rounds);
        preIncrement(rounds);
    }

    private static void postIncrement(final int rounds) {
        for (int i = 0; i < rounds; i++) {
            somethingToIncrement++;
        }
    }

    private static void preIncrement(final int rounds) {
        for (int i = 0; i < rounds; ++i) {
            ++somethingToIncrement;
        }
    }
}

A teraz dla kodu bajtowego (javap -private -c PreOrPostIncrement):

public class PreOrPostIncrement extends java.lang.Object{
static int somethingToIncrement;

static {};
Code:
0:  iconst_0
1:  putstatic   #10; //Field somethingToIncrement:I
4:  return

public PreOrPostIncrement();
Code:
0:  aload_0
1:  invokespecial   #15; //Method java/lang/Object."<init>":()V
4:  return

public static void main(java.lang.String[]);
Code:
0:  sipush  1000
3:  istore_1
4:  sipush  1000
7:  invokestatic    #21; //Method postIncrement:(I)V
10: sipush  1000
13: invokestatic    #25; //Method preIncrement:(I)V
16: return

private static void postIncrement(int);
Code:
0:  iconst_0
1:  istore_1
2:  goto    16
5:  getstatic   #10; //Field somethingToIncrement:I
8:  iconst_1
9:  iadd
10: putstatic   #10; //Field somethingToIncrement:I
13: iinc    1, 1
16: iload_1
17: iload_0
18: if_icmplt   5
21: return

private static void preIncrement(int);
Code:
0:  iconst_0
1:  istore_1
2:  goto    16
5:  getstatic   #10; //Field somethingToIncrement:I
8:  iconst_1
9:  iadd
10: putstatic   #10; //Field somethingToIncrement:I
13: iinc    1, 1
16: iload_1
17: iload_0
18: if_icmplt   5
21: return

}

5

Tak jest. Różnica polega na wartości zwracanej. Zwracana wartość „++ i” będzie wartością po inkrementacji i. Zwrot „i ++” będzie wartością przed inkrementacją. Oznacza to, że kod wygląda następująco:

int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.

Dlatego a będzie równe 2, a b i c będą równe 1.

Mógłbym przepisać kod w ten sposób:

int a = 0; 

// ++a;
a = a + 1; // incrementing first.
b = a; // setting second. 

// a++;
c = a; // setting first. 
a = a + 1; // incrementing second. 

4

W obu przypadkach nie ma faktycznej różnicy ' i' zostanie zwiększona o 1.

Ale jest różnica, gdy używasz go w wyrażeniu, na przykład:

int i = 1;
int a = ++i;
// i is incremented by one and then assigned to a.
// Both i and a are now 2.
int b = i++;
// i is assigned to b and then incremented by one.
// b is now 2, and i is now 3

3

++ i i ++ to coś więcej niż pętle i różnice w wydajności. ++ i zwraca wartość l, a i ++ zwraca wartość r. Na tej podstawie istnieje wiele rzeczy, które możesz zrobić (++ i), ale nie (i ++).

1- It is illegal to take the address of post increment result. Compiler won't even allow you.
2- Only constant references to post increment can exist, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal.
4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like:

T& operator ++ ( )
{
   // logical increment
   return *this;
}

const T operator ++ ( int )
{
    T temp( *this );
    ++*this;
    return temp;
}

3

Zastanawia mnie, dlaczego ludzie mogą pisać wyrażenie przyrostowe w pętli for jako i ++.

W pętli for, gdy trzeci składnik jest prostą instrukcją przyrostową, jak w

for (i=0; i<x; i++)  

lub

for (i=0; i<x; ++i)   

nie ma różnicy w wynikowych wykonaniach.


Czy to odpowiedź, czy pytanie?
Palec

2
Skoro to nie ma znaczenia, dlaczego miałoby to nękać umysł, czy ktoś napisał i ++? Czy jest jakiś powód, dla którego ktoś wolałby pisać ++ i?
Dronz

2

Jak mówi @Jon B , nie ma różnicy w pętli for.

Ale w pętli whilelub do...whilemożesz znaleźć pewne różnice, jeśli porównujesz z ++ilubi++

while(i++ < 10) { ... } //compare then increment

while(++i < 10) { ... } //increment then compare

dwa głosy negatywne? Co jest nie tak z tym, co napisałem? I ma to związek z pytaniem (jakkolwiek niejasnym).
crashmstr

2

W javascript z powodu następującego i ++ może być lepiej użyć:

var i=1;
alert(i++); // before, 1. current, 1. after, 2.
alert(i); // before, 2. current, 2. after, 2.
alert(++i); // before, 2. current, 3 after, 3.

Podczas gdy tablice (myślę, że wszystkie) oraz niektóre inne funkcje i wywołania używają 0 jako punktu początkowego, musiałbyś ustawić i na -1, aby pętla działała z tablicą podczas używania ++ i .

Podczas korzystania z i ++ następująca wartość wykorzysta zwiększoną wartość. Można powiedzieć, że i ++ to sposób, w jaki liczą się ludzie, ponieważ możesz zacząć od 0 .


2

Aby zrozumieć, co robi pętla FOR

wprowadź opis zdjęcia tutaj

Powyższy obraz pokazuje, że FOR można przekonwertować na WHILE , ponieważ ostatecznie mają one całkowicie ten sam kod asemblera (przynajmniej w gcc). Więc możemy rozbić FOR na kilka części, aby zrozumieć, co robi.

for (i = 0; i < 5; ++i) {
  DoSomethingA();
  DoSomethingB();
}

jest równa wersji WHILE

i = 0; //first argument (a statement) of for
while (i < 5 /*second argument (a condition) of for*/) {
  DoSomethingA();
  DoSomethingB();
  ++i; //third argument (another statement) of for
}

Oznacza to, że możesz użyć FOR jako prostej wersji WHILE :

  1. Pierwszy argument FOR (int i) jest wykonywany na zewnątrz przed pętlą.

  2. Trzeci argument FOR (i ++ lub ++ i) jest wykonywany wewnątrz w ostatnim wierszu pętli.

TL: DR: bez względu na to, czy i++lub ++i, wiemy, że gdy są samodzielne, nie mają znaczenia, ale dają +1 dla siebie.

W szkole zwykle uczą języka i ++, ale jest też wiele osób, które preferują język i ++ z kilku powodów .

UWAGA: W przeszłości i ++ miał bardzo mały wpływ na wydajność, ponieważ nie tylko sam plus jeden, ale także zachowuje oryginalną wartość w rejestrze. Ale na razie nie ma znaczenia, ponieważ kompilator sprawia, że ​​część dodatnia jest taka sama.


1

Różnice mogą występować w przypadku pętli. Jest to praktyczne zastosowanie post / przyrostu.

        int i = 0;
        while(i++ <= 10) {
            Console.Write(i);
        }
        Console.Write(System.Environment.NewLine);

        i = 0;
        while(++i <= 10) {
            Console.Write(i);
        }
        Console.ReadLine();

Podczas gdy pierwszy liczy się do 11 i zapętla 11 razy, drugi nie.

Najczęściej jest to używane raczej w krótkim czasie (x--> 0); - - Pętla iteruje na przykład wszystkie elementy tablicy (wyłączając tutaj konstrukcje foreach).


1

Obaj zwiększają liczbę. ++ijest równoważne z i = i + 1.

i++i ++isą bardzo podobne, ale nie dokładnie takie same. Oba zwiększają liczbę, ale ++izwiększają liczbę przed obliczeniem bieżącego wyrażenia, podczas gdy i++zwiększają liczbę po obliczeniu wyrażenia.

int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a = 

Sprawdź ten link .


0

Tak, istnieje różnica pomiędzy ++ii i++w forpętli, choć w nietypowych przypadkach użycia; gdy zmienna pętli z operatorem zwiększania / zmniejszania jest używana w bloku for lub w wyrażeniu testu pętli lub z jedną ze zmiennych pętli . Nie, nie jest to po prostu składnia.

Jak iw kodzie oznacza wyrażenie, ia operator nie oznacza oceny, a jedynie operację;

  • ++ioznacza wartość przyrostu o i1 i późniejszą ocenę i,
  • i++oznacza oszacowanie, ia następnie zwiększenie wartości o i1.

To, co jest otrzymywane z każdego z dwóch wyrażeń, różni się, ponieważ to, co jest oceniane, różni się w każdym z nich. Wszystko to samo dla --iii--

Na przykład;

let i = 0

i++ // evaluates to value of i, means evaluates to 0, later increments i by 1, i is now 1
0
i
1
++i // increments i by 1, i is now 2, later evaluates to value of i, means evaluates to 2
2
i
2

W nietypowych przypadkach, jednak następny przykład wydaje się przydatny lub nie ma znaczenia, pokazuje różnicę

for(i=0, j=i; i<10; j=++i){
    console.log(j, i)
}

for(i=0, j=i; i<10; j=i++){
    console.log(j, i)
}

Co to dodaje do istniejących odpowiedzi?
GManNickG

odpowiada bardziej bezpośrednio na pytania, niż te, które przeczytałem.
Selçuk

-2

W przypadku itypów zdefiniowanych przez użytkownika operatory te mogą (ale nie powinny ) mieć znacząco różne dane sematyczne w kontekście indeksu pętli, a to może (ale nie powinno) wpływać na zachowanie opisanej pętli.

Ponadto w c++zasadzie najbezpieczniej jest używać formularza wstępnego przyrostu ( ++i), ponieważ łatwiej go zoptymalizować. (Scott Langham pobił mnie na ten smakołyk . Przeklinam cię, Scott)


Semantyka postfiksa powinna być większa niż prefiks. -1
xtofl

-2

Dont wiem dla innych języków, ale w Javie ++ i jest prefiks przyrost który oznacza: zwiększenie I o 1, a następnie użyć nowej wartości I w wypowiedzi, w których I miejsce zamieszkania, a ja ++ jest przyrost postfix co oznacza, że następuje : użyj bieżącej wartości i w wyrażeniu, a następnie zwiększ ją o 1. Przykład:

public static void main(String [] args){

    int a = 3;
    int b = 5;
    System.out.println(++a);
    System.out.println(b++);
    System.out.println(b);

}, a wynik to:

  • 4
  • 5
  • 6

-3

i ++; ++ i; oba są podobne, ponieważ nie są używane w wyrażeniu.

class A {

     public static void main (String []args) {

     int j = 0 ;
     int k = 0 ;
     ++j;
     k++;
    System.out.println(k+" "+j);

}}

prints out :  1 1
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.