อัปเดตดูด้านล่าง!
ฉันเคยได้ยินและอ่านว่า C ++ 0x อนุญาตให้คอมไพเลอร์พิมพ์ "Hello" สำหรับตัวอย่างต่อไปนี้
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
เห็นได้ชัดว่ามีบางอย่างเกี่ยวข้องกับเธรดและความสามารถในการปรับให้เหมาะสม ฉันคิดว่ามันน่าแปลกใจที่หลาย ๆ คนคิดว่า
บางคนมีคำอธิบายที่ดีว่าเหตุใดจึงจำเป็นต้องอนุญาต สำหรับการอ้างอิง C ++ 0x ฉบับร่างล่าสุดระบุไว้ที่6.5/5
ลูปที่นอกเหนือจากคำสั่ง for-init ในกรณีของคำสั่ง for
- ไม่เรียกใช้ฟังก์ชันห้องสมุด I / O และ
- ไม่สามารถเข้าถึงหรือแก้ไขวัตถุที่ระเหยได้และ
- ไม่มีการดำเนินการซิงโครไนซ์ (1.10) หรือการดำเนินการปรมาณู (ข้อ 29)
อาจถูกสันนิษฐานโดยการนำไปปฏิบัติเพื่อยุติ [หมายเหตุ: สิ่งนี้มีจุดประสงค์เพื่อให้การแปลงคอมไพเลอร์เช่นการลบลูปที่ว่างเปล่าแม้ว่าจะไม่สามารถพิสูจน์ได้ว่าการเลิกจ้าง - บันทึกท้าย]
แก้ไข:
บทความที่ลึกซึ้งนี้กล่าวถึงข้อความมาตรฐาน
น่าเสียดายที่คำว่า "พฤติกรรมที่ไม่ได้กำหนด" ไม่ได้ใช้ อย่างไรก็ตามเมื่อใดก็ตามที่มาตรฐานบอกว่า "คอมไพเลอร์อาจถือว่า P" ก็หมายความว่าโปรแกรมที่มีคุณสมบัติที่ไม่ใช่ P มีความหมายที่ไม่ได้กำหนด
ถูกต้องและคอมไพเลอร์ได้รับอนุญาตให้พิมพ์ "Bye" สำหรับโปรแกรมข้างต้นหรือไม่
มีกระทู้ที่ลึกซึ้งยิ่งขึ้นที่นี่ซึ่งเป็นเรื่องเกี่ยวกับการเปลี่ยนแปลงคล้ายกับ C เริ่มต้นโดย Guy ทำบทความเชื่อมโยงข้างต้น ในบรรดาข้อเท็จจริงที่มีประโยชน์อื่น ๆ พวกเขานำเสนอโซลูชันที่ดูเหมือนว่าจะนำไปใช้กับ C ++ 0x ( อัปเดต : สิ่งนี้จะไม่ทำงานกับ n3225 - ดูด้านล่าง!)
endless:
goto endless;
คอมไพเลอร์ไม่ได้รับอนุญาตให้ปรับประสิทธิภาพให้เหมาะสมดูเหมือนเนื่องจากไม่ใช่การวนซ้ำ แต่เป็นการกระโดด ชายอีกคนสรุปการเปลี่ยนแปลงที่เสนอใน C ++ 0x และ C201X
โดยการเขียนห่วงโปรแกรมเมอร์ที่จะเข้าไปยุ่งเกี่ยวกับอย่างใดอย่างหนึ่งที่ห่วงทำอะไรบางอย่างที่มีพฤติกรรมที่มองเห็น (ดำเนินการ I / O, การเข้าถึงวัตถุระเหยหรือดำเนินการประสานการดำเนินงานหรืออะตอม) หรือว่าในที่สุดก็สิ้นสุดลง หากฉันละเมิดข้อสันนิษฐานนั้นโดยการเขียนลูปที่ไม่มีที่สิ้นสุดโดยไม่มีผลข้างเคียงฉันกำลังโกหกคอมไพเลอร์และพฤติกรรมของโปรแกรมของฉันไม่ได้กำหนดไว้ (ถ้าฉันโชคดีคอมไพเลอร์อาจเตือนฉันเกี่ยวกับเรื่องนี้) ภาษาไม่ได้ให้ (ไม่มีอีกต่อไปแล้ว?) วิธีการแสดงวงวนไม่สิ้นสุดโดยไม่มีพฤติกรรมที่มองเห็นได้
อัปเดตเมื่อวันที่ 3.1.2011 กับ n3225: คณะกรรมการย้ายข้อความไปที่ 1.10 / 24 และพูด
การนำไปใช้อาจสันนิษฐานว่าเธรดใด ๆ จะทำอย่างใดอย่างหนึ่งต่อไปนี้:
- ยกเลิก
- โทรไปยังฟังก์ชั่นไลบรารี I / O
- เข้าถึงหรือแก้ไขวัตถุที่ระเหยได้หรือ
- ดำเนินการประสานหรือการดำเนินการปรมาณู
goto
เคล็ดลับจะไม่ทำงานอีกต่อไป!
int x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
เป็นfor(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
หรือไม่? หรืออาจเป็นวิธีอื่นโดยมีx
การเตรียมใช้งาน2
ก่อนลูป มันสามารถบอกได้ว่าdo_something
ไม่สนใจคุณค่าของx
มันดังนั้นจึงเป็นการเพิ่มประสิทธิภาพที่ปลอดภัยอย่างสมบูรณ์แบบหาก do_something
ไม่ทำให้ค่าของi
การเปลี่ยนแปลงนั้นจบลงด้วยการวนซ้ำไม่สิ้นสุด
main() { start_daemon_thread(); while(1) { sleep(1000); } }
เพิ่งออกทันทีแทนที่จะใช้ภูตของฉันในด้ายพื้นหลัง?
while(1) { MyMysteriousFunction(); }
ต้องสามารถคอมไพล์ได้อย่างอิสระโดยไม่ทราบคำจำกัดความของฟังก์ชั่นลึกลับใช่มั้ย ดังนั้นเราจะทราบได้อย่างไรว่ามันทำการโทรไปยังฟังก์ชั่นไลบรารี I / O ใด ๆ กล่าวอีกนัยหนึ่ง: แน่นอนว่ากระสุนแรกอาจจะเป็นวลีทำให้ไม่สามารถเรียกใช้ฟังก์ชันได้