ความแตกต่างระหว่าง pre-increment และ post-increment ใน loop หรือไม่?


303

มีความแตกต่างใน++iและi++ในforวงหรือไม่? มันเป็นเพียงเรื่องไวยากรณ์หรือไม่?


3
รายการที่ซ้ำกัน: stackoverflow.com/questions/467322/…
Jon B

18
ฉันประหลาดใจกับจำนวนคำตอบที่พลาดจุดคำถามอย่างสมบูรณ์
แกรม Perrow

3
บางทีเราควรจะต้องประหลาดใจที่ไม่มีใครแก้ไขคำถามที่ต้องมีความชัดเจนมากขึ้น :)
จอน B

2
คำถามนี้สามารถนำไปใช้ C, Java, C ++, PHP, C #, JavaScript, JScript, วัตถุประสงค์ C: en.wikipedia.org/wiki/Category:C_programming_language_family
คริส S

1
คำตอบที่ดีโพสต์ที่นี่: stackoverflow.com/a/4706225/214296
Jim Fell

คำตอบ:


233

a ++ รู้จักกันในชื่อ postfix

เพิ่ม 1 เข้ากับ a ส่งคืนค่าเก่า

++ a เรียกว่าคำนำหน้า

เพิ่ม 1 ถึง a ส่งคืนค่าใหม่

ค#:

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++);
}

เอาท์พุท:

1
2
3
4

0
1
2
3

foreachและwhileลูปขึ้นอยู่กับประเภทที่เพิ่มขึ้นที่คุณใช้ สำหรับลูปแบบด้านล่างจะไม่สร้างความแตกต่างเนื่องจากคุณไม่ได้ใช้ค่าส่งคืนของ 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

หากใช้ค่าที่ประเมินแล้วประเภทของการเพิ่มจะมีความสำคัญ:

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

4
นี่ไม่ใช่สิ่งที่ผู้ใช้ร้องขอ
Dimitri

223

Pre-increment ++ i จะเพิ่มค่าของ i และประเมินเป็นค่าที่เพิ่มขึ้นใหม่

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

การเพิ่มขึ้นภายหลังi ++ จะเพิ่มค่าของ i และประเมินเป็นค่าที่ไม่ได้เพิ่มขึ้นดั้งเดิม

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

ใน C ++ มักจะต้องการการเพิ่มล่วงหน้าซึ่งคุณสามารถใช้ได้

นี่เป็นเพราะถ้าคุณใช้การเพิ่มภายหลังมันอาจต้องการคอมไพเลอร์เพื่อสร้างรหัสที่สร้างตัวแปรชั่วคราวเพิ่มเติม นี่เป็นเพราะทั้งค่าก่อนหน้าและค่าใหม่ของตัวแปรที่เพิ่มขึ้นจำเป็นต้องถูกเก็บไว้ที่ใดที่หนึ่งเพราะอาจจำเป็นต้องใช้ที่อื่นในนิพจน์ที่กำลังถูกประเมิน

ดังนั้นอย่างน้อยใน C ++ อาจมีความแตกต่างด้านประสิทธิภาพซึ่งเป็นแนวทางที่คุณเลือกใช้

นี่เป็นเพียงปัญหาหลักเมื่อตัวแปรที่เพิ่มขึ้นเป็นประเภทที่ผู้ใช้กำหนดด้วยตัวดำเนินการ ++ ที่ถูกแทนที่ สำหรับประเภทดั้งเดิม (int, ฯลฯ ) จะไม่มีความแตกต่างด้านประสิทธิภาพ แต่มันก็คุ้มค่าที่จะยึดติดกับตัวดำเนินการที่เพิ่มขึ้นล่วงหน้าเป็นแนวทางเว้นแต่ว่าตัวดำเนินการภายหลังที่เพิ่มขึ้นนั้นเป็นสิ่งที่จำเป็นอย่างแน่นอน

มีการสนทนาเพิ่มเติมได้ที่นี่:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm

ใน C ++ หากคุณใช้ STL คุณอาจใช้ลูปกับตัววนซ้ำ สิ่งเหล่านี้ส่วนใหญ่มีตัวดำเนินการ ++ ที่ถูกแทนที่ดังนั้นการผสานการเพิ่มล่วงหน้าเป็นความคิดที่ดี คอมไพเลอร์จะฉลาดขึ้นตลอดเวลาและใหม่กว่านั้นอาจสามารถทำการปรับให้เหมาะสมซึ่งหมายความว่าไม่มีความแตกต่างด้านประสิทธิภาพ - โดยเฉพาะอย่างยิ่งถ้าประเภทที่เพิ่มขึ้นนั้นถูกกำหนดไว้แบบอินไลน์ในไฟล์ส่วนหัว มีการนำวิธีการนั้นไปใช้และสามารถทราบได้ว่าการปรับให้เหมาะสมนั้นปลอดภัยที่จะดำเนินการอย่างไร ถึงกระนั้นมันก็ยังคงคุ้มค่าที่จะเพิ่มขึ้นล่วงหน้าเนื่องจากลูปได้รับการประหารชีวิตหลายครั้งและนี่หมายความว่าการปรับประสิทธิภาพเล็กน้อยจะได้รับการขยายในไม่ช้า


ในภาษาอื่นเช่น C # ที่ไม่สามารถโหลดโอเปอเรเตอร์ ++ ได้มากเกินไปจะไม่มีความแตกต่างด้านประสิทธิภาพ ใช้ในลูปเพื่อเลื่อนตัวแปรลูปตัวดำเนินการเพิ่มก่อนและหลังจะเทียบเท่า

การแก้ไข: อนุญาตการโหลดมากเกินไป ++ ใน C # ดูเหมือนว่าเมื่อเทียบกับ C ++ ใน c # คุณไม่สามารถโหลดรุ่นก่อนและหลังได้อย่างอิสระ ดังนั้นฉันจะสมมติว่าถ้าผลลัพธ์ของการเรียก ++ ใน C # ไม่ได้ถูกกำหนดให้กับตัวแปรหรือใช้เป็นส่วนหนึ่งของการแสดงออกที่ซับซ้อนจากนั้นคอมไพเลอร์จะลดรุ่นก่อนและหลังของรุ่น ++ ลงเป็นรหัสที่ทำงานอย่างเท่าเทียมกัน


102
มันจะไม่ได้รับที่ดีถ้า C ++ เป็นชื่อ ++ C แสดงให้เห็นว่าคุณสามารถเขียนรหัสดีที่สุดโดยใช้มัน ..
Naveen

9
ไม่ควรใช้โปรแกรมคอมไพเลอร์สมัยใหม่เพื่อปรับให้เหมาะสมเมื่อค่าผลลัพธ์ที่ได้จะถูกทิ้งอย่างชัดเจน
che

6
@che - พวกเขาทำเมื่อมันเป็นประเภทที่เรียบง่าย แต่คลาสที่โอเวอร์โหลดโอเปอเรเตอร์ ++ (เช่นตัววนซ้ำ) เป็นเรื่องราวที่แตกต่าง
Ferruccio

7
@che: นั่นเป็นคำถามที่ดี สาเหตุที่คอมไพเลอร์ C ++ ไม่ได้แทนที่ "CustomType ++;" ด้วย "++ CustomType;" เป็นเพราะไม่มีการรับประกันว่าทั้งฟังก์ชั่นที่ผู้ใช้กำหนดมีผลเหมือนกัน พวกเขาควร ... แต่ไม่มีการรับประกัน
Drew Dormann

2
@ michael.bartnett: จุดดีโอเวอร์โหลด ++ ใน C # ดูเหมือนจะมีให้บริการ ดูเหมือนว่าเมื่อเทียบกับ c ++ ใน c # คุณไม่สามารถโหลดรุ่นก่อนและหลังได้อย่างอิสระ ดังนั้นฉันจะสมมติว่าถ้าผลลัพธ์ของการเรียก ++ ใน C # ไม่ได้ถูกกำหนดให้กับตัวแปรหรือใช้เป็นส่วนหนึ่งของการแสดงออกที่ซับซ้อนจากนั้นคอมไพเลอร์จะลดรุ่นก่อนและหลังของรุ่น ++ ลงเป็นรหัสที่ทำงานอย่างเท่าเทียมกัน
Scott Langham

83

ใน C # ไม่มีความแตกต่างเมื่อใช้ในการวน

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

ส่งออกเช่นเดียวกับ

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

อย่างที่คนอื่น ๆ ชี้เมื่อใช้โดยทั่วไปแล้วฉัน ++ มีความแตกต่างที่สำคัญ:

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

i ++ อ่านค่าของ i จากนั้นเพิ่มค่า

++ ฉันเพิ่มค่าของ i จากนั้นอ่านมัน


สรุป: ความหมายที่เพิ่มขึ้นโพสต์ / ก่อนเช่นเดียวกับใน C ++
xtofl

@xtofl - ไม่แน่ใจว่าประเด็นของคุณคืออะไร? ฉันเพิ่งเกิดขึ้นเพื่อเลือก c # สำหรับตัวอย่างของฉัน
Jon B

3
ฉันไม่คิดว่าประเด็นแรกเกี่ยวข้องกัน ในห่วงสำหรับ (c # หรือไม่) ส่วนที่เพิ่มขึ้นจะถูกดำเนินการเสมอหลังจากที่ร่างกายของวง เมื่อดำเนินการแล้วตัวแปรจะถูกแก้ไขไม่ว่าจะเป็นการเพิ่มหรือเพิ่มภายหลังการโพสต์
MatthieuP

9
@ MatthieuP - ฉันอ่านคำถามว่า "ไม่สำคัญว่าคุณจะใช้ i ++ หรือ ++ i ใน a for for loop" หรือไม่ คำตอบคือ "ไม่มันไม่ได้"
Jon B

1
@JonB ลำดับการดำเนินการในคำตอบนั้นไม่ถูกต้องอย่างแน่นอน ทั้งสอง++iและi++ดำเนินการเดียวกันในลำดับเดียวกัน: สร้าง temp copy ของi; เพิ่มค่า temp เพื่อสร้างค่าใหม่ (ไม่แทนที่ค่า temp); เก็บค่าใหม่ในi; ตอนนี้ถ้าเป็น++iผลลัพธ์ที่ส่งคืนคือค่าใหม่ หากเป็นi++ผลลัพธ์ที่ส่งคืนคือสำเนาชั่วคราว คำตอบโดยละเอียดเพิ่มเติมได้ที่นี่: stackoverflow.com/a/3346729/3330348
PiotrWolkowski

51

คำถามคือ:

มีความแตกต่างใน ++ i และ i ++ ใน for for loop หรือไม่?

คำตอบคือ: ไม่ไม่มี

ทำไมคำตอบแต่ละข้อจึงต้องอธิบายอย่างละเอียดเกี่ยวกับการเพิ่มขึ้นก่อนและหลังการโพสต์เมื่อไม่ได้ถาม

สำหรับวงนี้:

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

จะแปลเป็นรหัสนี้โดยไม่ใช้ลูป:

int i = 0; // Initialization

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

   i++ or ++i; // Increment

   goto loopStart;
}

ตอนนี้มันสำคัญไหมถ้าคุณใส่i++หรือ++iเพิ่มที่นี่? ไม่มันไม่ได้เป็นค่าตอบแทนของการดำเนินการเพิ่มขึ้นที่ไม่มีนัยสำคัญ iจะถูกเพิ่มค่าหลังจากการเรียกใช้โค้ดที่อยู่ภายใน for loop body


2
นี่คือคำตอบแรกที่เข้ามาในประเด็น ขอบคุณ
Yassir

1
ไม่ใช่คำตอบที่ดีที่สุดเพราะถ้า for loop เพิ่มวัตถุที่ซับซ้อน (อย่างอื่นที่ไม่ใช่ int!) การใช้ ++ x อาจเร็วกว่า x ++ ... (ดูherbalutter.com/2013/05/13/gotw -2-solution-temporary-objects )
JCx

30

เมื่อคุณถามถึงความแตกต่างในลูปฉันเดาว่าคุณหมายถึง

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

ในกรณีนี้คุณไม่มีความแตกต่างในภาษาส่วนใหญ่: การวนซ้ำจะทำงานเหมือนกันไม่ว่าคุณจะเขียนi++หรือ++iไม่ก็ตาม ใน C ++ คุณสามารถเขียนโอเปอเรเตอร์ ++ เวอร์ชันของคุณเองและคุณสามารถกำหนดความหมายแยกต่างหากสำหรับพวกเขาหากiเป็นประเภทที่ผู้ใช้กำหนด (เช่นคลาสของคุณเอง)

i++เหตุผลที่ว่าทำไมมันไม่สำคัญดังกล่าวข้างต้นเป็นเพราะคุณไม่ได้ใช้ค่าของ อีกอย่างคือเมื่อคุณทำ

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

ขณะนี้มีเป็นความแตกต่างเพราะเป็นคนอื่นชี้ให้เห็นi++วิธีการเพิ่ม แต่ประเมินค่าก่อนหน้าแต่++iหมายถึงการเพิ่มขึ้น แต่ประเมินi (จึงจะประเมินค่าใหม่) ในกรณีข้างต้นaได้รับการกำหนดค่าก่อนหน้าของฉันในขณะที่ฉันจะเพิ่มขึ้น


3
ใน C ++ มันเป็นไปไม่ได้เสมอที่คอมไพเลอร์จะหลีกเลี่ยงการสร้างชั่วคราวดังนั้นจึงต้องการแบบฟอร์มการเพิ่มล่วงหน้า
David Thornley

อย่างที่ฉันเขียนถ้าคุณมีประเภทผู้ใช้ที่กำหนดไว้พวกเขาอาจมีความหมายต่างกัน แต่ถ้าคุณใช้ i ชนิดพื้นฐานแล้วมันจะไม่สร้างความแตกต่างสำหรับลูปแรก เนื่องจากนี่เป็นคำถามที่ไม่เชื่อเรื่องภาษาฉันคิดว่าจะไม่เขียนเนื้อหาเฉพาะเกี่ยวกับ C ++ มากเกินไป
Johannes Schaub - litb

15

ตามที่รหัสนี้แสดง (ดู MSIL ที่แยกส่วนในความคิดเห็น) คอมไพเลอร์ C # 3 ไม่ได้แยกความแตกต่างระหว่าง i ++ และ ++ i ใน a for loop หากค่าของ i ++ หรือ ++ ฉันถูกใช้ไปมันจะมีความแตกต่างอย่างแน่นอน (ซึ่งถูกรวบรวมใน Visutal Studio 2008 / Build Release):

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

หนึ่ง (++ i) คือส่วนนำหน้าหนึ่งส่วน (i ++) คือส่วนหน้าหลัง ความแตกต่างคือสิ่งที่ค่าจะถูกส่งกลับทันทีจากการแสดงออก

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

แก้ไข: Woops เพิกเฉยต่อด้านวนของสิ่งต่าง ๆ ทั้งหมด สำหรับลูปไม่มีความแตกต่างจริงเมื่อเป็นส่วน 'ขั้นตอน' (สำหรับ (... ; ... ;)) แต่มันสามารถเล่นได้ในกรณีอื่น ๆ


7

ไม่มีความแตกต่างถ้าคุณไม่ได้ใช้ค่าหลังจากการเพิ่มในลูป

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

ลูปทั้งสองจะพิมพ์ 0123

แต่ความแตกต่างเกิดขึ้นเมื่อคุณใช้ค่าหลังจากการเพิ่ม / ลดในวงของคุณดังนี้:

การเพิ่มวงก่อน:

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

เอาท์พุต: 0 0 1 1 2 2 3 3

โพสต์ลูปเพิ่ม:

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

เอาท์พุท: 0 0 1 0 2 1 3 2

ฉันหวังว่าความแตกต่างชัดเจนโดยเปรียบเทียบผลลัพธ์ ชี้ไปที่นี่คือการเพิ่ม / ลดลงจะดำเนินการเสมอในตอนท้ายของการวนรอบและดังนั้นจึงสามารถอธิบายผลลัพธ์ได้


7

นี่คือตัวอย่าง Java และ Byte-Code, post- และ preIncrement ไม่แสดงความแตกต่างใน Bytecode:

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;
        }
    }
}

และตอนนี้สำหรับรหัสไบต์ (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

ใช่แล้ว ความแตกต่างอยู่ในค่าส่งคืน ค่าส่งคืนของ "++ i" จะเป็นค่าหลังจากเพิ่มค่าi การคืนค่าของ "i ++" จะเป็นค่าก่อนการเพิ่ม ซึ่งหมายความว่ารหัสที่มีลักษณะดังต่อไปนี้:

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.

ดังนั้น a จะเท่ากับ 2 และ b และ c แต่ละอันจะเป็น 1

ฉันสามารถเขียนรหัสเช่นนี้ได้:

int a = 0; 

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

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

4

ไม่มีความแตกต่างจริงในทั้งสองกรณี ' i' จะเพิ่มขึ้น 1

แต่มีความแตกต่างเมื่อคุณใช้มันในการแสดงออกเช่น:

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 ++ มากกว่าลูปและความแตกต่างด้านประสิทธิภาพ ++ ฉันส่งคืนค่า l และ i ++ ส่งคืนค่า r จากสิ่งนี้มีหลายสิ่งที่คุณสามารถทำได้เพื่อ (++ i) แต่ไม่ถึง (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

มันทำให้ฉันนึกไม่ออกว่าทำไมคนอื่นถึงเขียนนิพจน์ที่เพิ่มขึ้นใน for-loop เป็น i ++

ใน for-loop เมื่อองค์ประกอบที่ 3 เป็นคำสั่งที่เพิ่มขึ้นอย่างง่ายเช่นเดียวกับใน

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

หรือ

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

ไม่มีความแตกต่างในการประหารชีวิตที่เกิดขึ้น


มันเป็นคำตอบหรือเป็นคำถาม?
Palec

2
เนื่องจากมันไม่สำคัญว่าทำไมมันจึงทำให้ใจของคุณสับสนว่ามีคนเขียน i ++ หรือไม่ มีเหตุผลไหมที่บางคนอยากเขียน ++ i?
Dronz

2

ตามที่@Jon Bพูดว่าไม่มีความแตกต่างในการวนรอบ

แต่ใน a whileหรือdo...whileloop คุณสามารถค้นหาความแตกต่างได้ถ้าคุณทำการเปรียบเทียบกับ++iหรือi++

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

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

สอง downvotes? เกิดอะไรขึ้นกับสิ่งที่ฉันเขียน? และมันเกี่ยวข้องกับคำถาม (คลุมเครือเหมือนเดิม)
crashmstr

2

ใน javascript เนื่องจาก i ++ ต่อไปนี้อาจใช้งานได้ดีกว่า:

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.

ในขณะที่อาร์เรย์ (ฉันคิดว่าทั้งหมด) และบางฟังก์ชั่นอื่น ๆ และบริการโทร 0 ใช้เป็นจุดเริ่มต้นที่คุณจะต้องตั้ง i เพื่อ -1 จะทำให้การทำงานวงกับอาร์เรย์เมื่อใช้++ฉัน

เมื่อใช้i ++ค่าต่อไปนี้จะใช้ค่าที่เพิ่มขึ้น คุณอาจจะบอกฉัน ++เป็นวิธีที่นับมนุษย์ทำให้คุณสามารถเริ่มต้นด้วย0


2

เพื่อให้เข้าใจสิ่งที่วงFORทำ

ป้อนคำอธิบายรูปภาพที่นี่

ภาพด้านบนแสดงให้เห็นว่าFORสามารถแปลงเป็นWHILE ได้ในขณะที่พวกเขามีรหัสแอสเซมบลีเดียวกันทั้งหมด (อย่างน้อยเป็น gcc) ดังนั้นเราสามารถแบ่งย่อยFORเป็นชิ้น ๆ เพื่อทำสิ่งที่มันทำ

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

เท่ากับรุ่นในขณะที่

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
}

หมายความว่าคุณสามารถใช้FORเป็นเวอร์ชันง่าย ๆในขณะที่ :

  1. อาร์กิวเมนต์แรกของFOR (int i) ถูกเรียกใช้ภายนอกก่อนลูป

  2. อาร์กิวเมนต์ที่สามของFOR (i ++ หรือ ++ i) ถูกดำเนินการภายในในบรรทัดสุดท้ายของลูป

TL: DR: ไม่ว่าจะเป็นi++หรือ++iเราจะรู้ว่าพวกเขาเป็นแบบสแตนด์อโลนพวกเขาไม่ได้สร้างความแตกต่างเลย

ในโรงเรียนพวกเขามักจะสอนฉัน ++ ทาง แต่ก็ยังมีผู้คนจำนวนมากชอบ ++ i ทางเนื่องจากเหตุผลหลายประการ

หมายเหตุ:ในอดีต i ++ มีผลกระทบต่อประสิทธิภาพการทำงานน้อยมากเนื่องจากไม่เพียง แต่จะเพิ่มให้กับตัวมันเอง แต่ยังเก็บค่าดั้งเดิมไว้ในรีจิสเตอร์ด้วย แต่สำหรับตอนนี้มันไม่ได้ทำให้ความแตกต่างเพราะคอมไพเลอร์ทำให้ส่วนที่เป็นบวกเหมือนกัน


1

อาจมีความแตกต่างสำหรับลูป นี่คือการใช้งานจริงของการโพสต์ / เพิ่มขึ้น

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

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

ในขณะที่คนแรกนับถึง 11 และลูป 11 ครั้งที่สองไม่ได้

ส่วนใหญ่จะใช้ค่อนข้างง่ายในขณะที่ (x--> 0); - - วนซ้ำเช่นองค์ประกอบทั้งหมดของอาร์เรย์ (ยกเว้น foreach-constructs ที่นี่)


1

พวกเขาทั้งสองเพิ่มจำนวน เทียบเท่ากับ++ii = i + 1

i++และ++iคล้ายกันมาก แต่ไม่เหมือนกันทุกประการ ทั้งเพิ่มจำนวน แต่++iเพิ่มจำนวนก่อนการแสดงออกปัจจุบันมีการประเมินในขณะที่i++เพิ่มจำนวนหลังจากการแสดงออกการประเมิน

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

ตรวจสอบลิงค์นี้


0

ใช่มีความแตกต่างระหว่าง ++iและi++ในforลูป แต่ในกรณีการใช้งานที่ผิดปกติ; เมื่อตัวแปรลูปที่มีตัวดำเนินการเพิ่ม / ลดลงใช้สำหรับบล็อกหรือภายในนิพจน์การทดสอบลูปหรือกับหนึ่งในตัวแปรลูปกับหนึ่งในตัวแปรห่วงไม่มันไม่ใช่เพียงเรื่องไวยากรณ์

ในฐานะที่เป็นiในรหัสวิธีการประเมินการแสดงออกiและผู้ประกอบการไม่ได้หมายความว่าการประเมินผล แต่เพียงการดำเนินการ;

  • ++iหมายถึงมูลค่าที่เพิ่มขึ้นi1 และประเมินในภายหลังi ,
  • i++หมายถึงประเมินiและเพิ่มมูลค่าในภายหลังiโดย 1

ดังนั้นสิ่งที่ได้รับจากแต่ละนิพจน์นั้นต่างกันเพราะสิ่งที่ประเมินนั้นแตกต่างกันไปในแต่ละนิพจน์ เหมือนกันทั้งหมดสำหรับ--iและi--

ตัวอย่างเช่น;

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

ในกรณีที่ใช้งานผิดปกติอย่างไรก็ตามตัวอย่างต่อไปฟังดูมีประโยชน์หรือไม่สำคัญก็แสดงให้เห็นถึงความแตกต่าง

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)
}

สิ่งนี้เพิ่มอะไรมากกว่าคำตอบที่มีอยู่
GManNickG

มันตอบได้โดยตรงมากกว่าสิ่งที่ถามกว่าคำตอบที่ฉันอ่าน
Selçuk

-2

สำหรับiประเภทที่ผู้ใช้กำหนดผู้ประกอบการเหล่านี้สามารถ (แต่ไม่ควร ) มีความหมายที่แตกต่างกันอย่างมีนัยสำคัญในบริบทของดัชนีลูปและสิ่งนี้สามารถ (แต่ไม่ควร) ส่งผลกระทบต่อพฤติกรรมของวงที่อธิบายไว้

นอกจากนี้ในc++นั้นโดยทั่วไปจะปลอดภัยที่สุดที่จะใช้แบบฟอร์มการเพิ่มขึ้นล่วงหน้า ( ++i) เพราะมันเหมาะที่สุดได้ง่ายขึ้น (สกอตต์แลงแฮมเอาชนะฉันถึงอาหารอันโอชะนี้สาปแช่งคุณสกอตต์)


ซีแมนทิกส์ของ postfix ควรใหญ่กว่า prefix -1
xtofl

-2

ฉันไม่รู้สำหรับภาษาอื่น แต่ใน Java ++ iเป็นการเพิ่มส่วนนำหน้าซึ่งหมายถึง: เพิ่มiด้วย 1 จากนั้นใช้ค่าใหม่ของ i ในนิพจน์ที่ฉันอยู่และi ++เป็นการเพิ่ม postfixซึ่งหมายถึงสิ่งต่อไปนี้ : ใช้ค่าปัจจุบันของiในนิพจน์แล้วเพิ่มเป็น 1 ตัวอย่าง:

public static void main(String [] args){

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

} และผลลัพธ์คือ:

  • 4
  • 5
  • 6

-3

ฉัน ++; ++ i; ทั้งสองมีความคล้ายคลึงกันเนื่องจากไม่ได้ใช้ในการแสดงออก

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.