ลำดับของการเรียกใช้ฟังก์ชัน (C++)

result= function_1()*function_2();

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


person oicrisah    schedule 29.10.2014    source แหล่งที่มา


คำตอบ (2)


ลำดับการประเมินไม่ได้ระบุโดยมาตรฐาน C++ (หรือ C) (ดู คำตอบจาก Vlad) หาก function_1 หรือ function_2 ของคุณมีผลข้างเคียงที่มีนัยสำคัญ ก็อาจกลายเป็น < a href="http://en.wikipedia.org/wiki/Unspecified_behavior" rel="nofollow noreferrer">พฤติกรรมที่ไม่ระบุ ที่คุณควรหลีกเลี่ยงอย่างยิ่ง (เช่นเดียวกับที่คุณควรหลีกเลี่ยง พฤติกรรมที่ไม่ได้กำหนด) และในบางกรณี (ฟังก์ชันแบบอินไลน์ที่มีการเพิ่มประสิทธิภาพที่แข็งแกร่ง) การคำนวณอาจมีการผสมผสานกัน

ลองนึกถึงกรณีแปลกๆ เช่น

 static int i;
 int function_1(void) { i++; return i; }
 int function_2(void) { i+=2; return 3*i+1; }

อาจเป็นการดำเนินการเฉพาะเจาะจง และอาจขึ้นอยู่กับคอมไพเลอร์จริงและแฟล็ก การเพิ่มประสิทธิภาพ

คุณควรเขียนโค้ดราวกับว่าลำดับของการเรียกใช้ฟังก์ชันนั้นเป็นแบบสุ่มโดยสมบูรณ์และไม่สามารถทำซ้ำได้ (แม้ว่า ในทางปฏิบัติ มันอาจจะทำซ้ำได้ก็ตาม) ในทำนองเดียวกัน คุณไม่ควรคาดหวังลำดับการประเมินอาร์กิวเมนต์ใดๆ เป็นพิเศษ (เช่น ใน f(i++, ++j) คุณไม่รู้ว่า i หรือ j ได้ถูกเพิ่มขึ้นก่อนหรือไม่) แม้ว่าสำหรับคอมไพเลอร์ที่กำหนดนั้น ลำดับนั้นอาจได้รับการแก้ไขก็ตาม ขอย้ำอีกครั้งว่าคุณควรจินตนาการถึงลำดับแบบสุ่มโดยสิ้นเชิงและไม่สามารถทำซ้ำได้

ตามที่แสดงความคิดเห็นโดย David Schwartz หากคุณสนใจเกี่ยวกับคำสั่งซื้อ คุณควรเขียนโค้ด จุดลำดับ

ในที่สุด หากโค้ดของคุณขึ้นอยู่กับลำดับบางอย่าง มันก็ไม่สามารถอ่านได้อย่างสมบูรณ์ และด้วยเหตุผลง่ายๆ ในการอ่าน คุณควรหลีกเลี่ยงการเขียนโค้ดด้วยวิธีนี้

person Basile Starynkevitch    schedule 29.10.2014
comment
หากคุณสนใจ คุณจะต้องแทรกจุดลำดับระหว่างการเรียกใช้ฟังก์ชัน ชอบ result=function_1(); result*=function_2(); - person David Schwartz; 29.10.2014
comment
สิ่งนี้ไม่สามารถทำให้เกิดการทำงานที่ไม่ได้กำหนดได้ (เว้นแต่ function_1 หรือ function_2 เป็นมาโคร) มีจุดลำดับก่อนและหลังเนื้อฟังก์ชัน - person M.M; 29.10.2014
comment
หาก function_1 และ function_2 อยู่ในบรรทัด ฉันเชื่อว่าคอมไพเลอร์อาจปรับให้เหมาะสมเพื่อผสมโค้ดทั้งสอง... - person Basile Starynkevitch; 29.10.2014
comment
มันยังไม่สามารถทำให้เกิด UB ได้ คอมไพเลอร์ต้องปฏิบัติตามกฎเสมือน - person M.M; 29.10.2014
comment
ขอขอบคุณเกี่ยวกับ UB. ปรับปรุงคำตอบของฉัน! - person Basile Starynkevitch; 29.10.2014
comment
นี่ไม่ได้ระบุคลุมเครือเกินไป ดูเหมือนว่ามาตรฐาน C++ จะไม่พูดอะไรเกี่ยวกับเรื่องนี้ แต่มันก็เป็นเช่นนั้น ระบุว่าไม่ได้ระบุลำดับการประเมิน ดังนั้น ข้อความที่ชัดเจนยิ่งขึ้นก็คือว่าลำดับการประเมินนิพจน์ย่อยไม่ได้ระบุ - person Kerrek SB; 29.10.2014
comment
ฉันคิดว่าการคูณให้ผลลัพธ์เหมือนกันในทั้งสองกรณี (ประเมินทางซ้ายก่อน หรือประเมินทางขวาก่อน) ข้อกังวลนี้สามารถตรวจสอบได้โดยการใส่จุดพักในแต่ละฟังก์ชันและการทดสอบ โดยที่ complier ที่ใช้จะเป็นไปตามลำดับใด - person Ali Kazmi; 29.10.2014
comment
ไม่ใช่กับ static int i; int function_1(void) {i+=1; return i;}; int function_2(void) {i+=2; return i;} - person Basile Starynkevitch; 29.10.2014

ตามมาตรฐาน C++ (การทำงานของโปรแกรม 1.9)

15 ยกเว้นในกรณีที่ระบุไว้ การประเมินตัวถูกดำเนินการของตัวดำเนินการแต่ละรายและนิพจน์ย่อยของนิพจน์แต่ละรายการจะไม่เรียงลำดับกัน

ดังนั้นในนิพจน์นี้

result= function_1()*function_2();

คอมไพเลอร์บางตัวสามารถประเมินได้ตั้งแต่แรก function_1() จากนั้นจึง function_2() ในขณะที่คอมไพเลอร์อื่นๆ สามารถประเมินได้ตั้งแต่แรก function_2() และหลังจากนั้นเท่านั้น function_1() แม้จะเขียนแบบว่า.

result= (function_1())*(function_2());

or

result= (function_1())*function_2();

or

result= function_1()*(function_2());

จะไม่มีอะไรเปลี่ยนแปลงเมื่อเทียบกับลำดับการประเมินตัวถูกดำเนินการ

person Vlad from Moscow    schedule 29.10.2014