ถ้าเรามีฟังก์ชันสามอย่าง (foo, bar และ baz) ที่ประกอบกันเช่นนั้น ...
foo(bar(), baz())
มีการรับประกันใด ๆ ตามมาตรฐาน C ++ ที่แถบจะได้รับการประเมินก่อน baz?
ถ้าเรามีฟังก์ชันสามอย่าง (foo, bar และ baz) ที่ประกอบกันเช่นนั้น ...
foo(bar(), baz())
มีการรับประกันใด ๆ ตามมาตรฐาน C ++ ที่แถบจะได้รับการประเมินก่อน baz?
คำตอบ:
ไม่ไม่มีการรับประกันดังกล่าว ไม่ได้ระบุตามมาตรฐาน C ++
Bjarne Stroustrup ยังกล่าวอย่างชัดเจนใน "The C ++ Programming Language" 3rd edition section 6.2.2 โดยมีเหตุผลบางประการ:
สามารถสร้างโค้ดที่ดีขึ้นได้โดยไม่มีข้อ จำกัด ในลำดับการประเมินนิพจน์
แม้ว่าในทางเทคนิคแล้วสิ่งนี้หมายถึงส่วนก่อนหน้าของส่วนเดียวกันซึ่งกล่าวว่าลำดับของการประเมินส่วนของนิพจน์นั้นไม่ได้ระบุไว้เช่นกันเช่น
int x = f(2) + g(3); // unspecified whether f() or g() is called first
จาก [5.2.2] การเรียกใช้ฟังก์ชัน
ลำดับของการประเมินข้อโต้แย้งไม่ได้ระบุไว้ ผลข้างเคียงทั้งหมดของการประเมินนิพจน์อาร์กิวเมนต์จะมีผลก่อนป้อนฟังก์ชัน
ดังนั้นจึงมีการรับประกันว่าไม่มีbar()
จะทำงานก่อนbaz()
เท่านั้นที่bar()
และจะถูกเรียกว่าก่อนที่จะbaz()
foo
นอกจากนี้โปรดทราบจาก [5] นิพจน์ที่:
ยกเว้นในกรณีที่ระบุไว้ [เช่นกฎพิเศษสำหรับ
&&
และ||
] ลำดับของการประเมินตัวถูกดำเนินการของแต่ละตัวดำเนินการและนิพจน์ย่อยของนิพจน์แต่ละรายการและลำดับที่เกิดผลข้างเคียงไม่ได้ระบุไว้
ดังนั้นแม้ว่าคุณจะถูกถามว่าbar()
จะเรียกใช้ก่อนbaz()
ในfoo(bar() + baz())
การสั่งซื้อยังคงไม่ได้ระบุ
&
, &&
การค้ำประกันจากซ้ายไปขวาประเมินผลตัวถูกดำเนินการที่สองคือการไม่ได้รับการประเมินถ้าตัวถูกดำเนินการแรกคือfalse
."
ไม่มีลำดับที่ระบุสำหรับ bar () และ baz () - สิ่งเดียวที่ Standard กล่าวคือทั้งคู่จะได้รับการประเมินก่อนที่จะเรียก foo () จากมาตรฐาน C ++ ส่วน 5.2.2 / 8:
ลำดับของการประเมินข้อโต้แย้งไม่ได้ระบุไว้
bar
นั้นบรรทัดที่ 1 จากbaz
นั้นบรรทัดที่ 2 ของbar
ฯลฯ ) ซึ่งก็ดีเช่นกัน :-)
C ++ 17 ระบุลำดับการประเมินสำหรับตัวดำเนินการที่ไม่ได้ระบุจนถึง C ++ 17 ดูคำถามอะไรคือคำสั่งค้ำประกันการประเมินที่แนะนำโดย C ++ 17? แต่สังเกตการแสดงออกของคุณ
foo(bar(), baz())
ยังไม่ได้ระบุลำดับการประเมิน
ใน C ++ 11 ข้อความที่เกี่ยวข้องสามารถพบได้ใน8.3.6 อาร์กิวเมนต์เริ่มต้น / 9 (เน้นของฉัน)
อาร์กิวเมนต์ดีฟอลต์จะถูกประเมินทุกครั้งที่เรียกใช้ฟังก์ชัน ลำดับของการประเมินผลของการขัดแย้งฟังก์ชั่นที่ไม่ได้ระบุ ดังนั้นจึงห้ามใช้พารามิเตอร์ของฟังก์ชันในอาร์กิวเมนต์เริ่มต้นแม้ว่าจะไม่ได้รับการประเมินก็ตาม
ใช้คำฟุ่มเฟือยเดียวกันถูกใช้โดย C ++ 14 มาตรฐานเช่นกันและพบว่าภายใต้หัวข้อเดียวกัน
ตามที่คนอื่น ๆ ได้ชี้ให้เห็นแล้วมาตรฐานไม่ได้ให้คำแนะนำใด ๆ เกี่ยวกับลำดับการประเมินสำหรับสถานการณ์เฉพาะนี้ จากนั้นลำดับของการประเมินผลจะถูกปล่อยให้คอมไพเลอร์และคอมไพเลอร์อาจมีการรับประกัน
สิ่งสำคัญคือต้องจำไว้ว่ามาตรฐาน C ++ เป็นภาษาที่ใช้สั่งคอมไพเลอร์ในการสร้างรหัสแอสเซมบลี / เครื่อง มาตรฐานเป็นเพียงส่วนหนึ่งของสมการ ในกรณีที่มาตรฐานไม่ชัดเจนหรือมีการกำหนดการนำไปใช้โดยเฉพาะคุณควรหันไปใช้คอมไพเลอร์และทำความเข้าใจว่าจะแปลคำสั่ง C ++ เป็นภาษาเครื่องจริงอย่างไร
ดังนั้นหากลำดับของการประเมินผลเป็นข้อกำหนดหรืออย่างน้อยก็สำคัญและการทำงานร่วมกันระหว่างคอมไพเลอร์ไม่ได้เป็นข้อกำหนดให้ตรวจสอบว่าคอมไพเลอร์ของคุณจะรวมสิ่งนี้เข้าด้วยกันในท้ายที่สุดคำตอบของคุณอาจอยู่ที่นั่นได้อย่างไร โปรดทราบว่าคอมไพลเลอร์สามารถเปลี่ยนวิธีการได้ในอนาคต