การใช้ตัวแปรใน initializer ของตัวเอง


22

[basic.scope.pdecl] / 1ของร่างมาตรฐาน C ++ 20 มีตัวอย่าง (ไม่ใช่กฎเกณฑ์) ดังต่อไปนี้ในบันทึกย่อ (อ้างบางส่วนจากก่อนที่จะรวมคำขอดึง 3580ดูคำตอบสำหรับคำถามนี้):

unsigned char x = x;

[... ] x ถูกเตรียมใช้งานด้วยค่าของตัวเอง (ไม่ทราบแน่ชัด)

สิ่งนี้มีพฤติกรรมที่ชัดเจนใน C ++ 20 หรือไม่


โดยทั่วไปการกำหนดค่าเริ่มต้นด้วยตนเองของแบบฟอร์มT x = x;จะมีพฤติกรรมที่ไม่ได้กำหนดโดยอาศัยคุณค่าของxการไม่ได้กำหนดค่าก่อนที่การเริ่มต้นจะเสร็จสมบูรณ์ การประเมินค่าที่ไม่ทราบแน่ชัดมักทำให้เกิดพฤติกรรมที่ไม่ได้กำหนด ( [basic.indent] / 2 ) แต่มีข้อยกเว้นเฉพาะใน[basic.indent] /2.3ที่อนุญาตให้เริ่มต้นunsigned charตัวแปรโดยตรงจากค่า lvalue unsigned charด้วยค่าที่ไม่ทราบแน่ชัด )

นี้เพียงอย่างเดียวไม่ดังนั้นจึงไม่ก่อให้เกิดพฤติกรรมที่ไม่ได้กำหนด แต่จะประเภทอื่น ๆTที่ไม่ได้รับการรับรองรูปแบบตัวอักษรหรือแคบเช่นstd::byte int x = x;ข้อควรพิจารณาเหล่านี้มีผลใน C ++ 17 และก่อนหน้านี้เช่นกันโปรดดูคำถามที่เชื่อมโยงที่ด้านล่าง

อย่างไรก็ตามสำหรับunsigned char x = x;ร่าง[basic.lifetime] / 7ของร่างปัจจุบันกล่าวว่า:

ในทำนองเดียวกันก่อนอายุการใช้งานของวัตถุได้เริ่ม [... ] โดยใช้คุณสมบัติของ glvalue ที่ไม่ได้ขึ้นอยู่กับค่าของมันจะถูกกำหนดไว้อย่างดี โปรแกรมมีพฤติกรรมที่ไม่ได้กำหนดหาก:

  • ใช้ glvalue เพื่อเข้าถึงวัตถุหรือ

  • [ ... ]

สิ่งนี้ดูเหมือนจะบอกเป็นนัยว่าxค่าในตัวอย่างสามารถใช้ได้ในช่วงชีวิตเท่านั้น

[basic.lifetime] / 1พูดว่า:

[ ... ]

อายุการใช้งานของวัตถุประเภท T เริ่มต้นเมื่อ:

  • [... ] และ
  • การเริ่มต้น (ถ้ามี) เสร็จสมบูรณ์ (รวมถึงการเริ่มต้นที่ว่าง) ([dcl.init])

[ ... ]

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

การวิเคราะห์ของฉันถูกต้องหรือไม่และหากมีผลต่อกรณีที่คล้ายกันของการใช้งานก่อนเริ่มต้นเช่น

int x = (x = 1);

สิ่งที่เท่าที่ฉันสามารถบอกได้มีการกำหนดไว้อย่างดีใน C ++ 17 และมาก่อนเช่นกัน?


โปรดทราบว่าใน C ++ 17 (ฉบับร่างสุดท้าย) ข้อกำหนดที่สองสำหรับอายุการใช้งานในการเริ่มต้นนั้นแตกต่างกัน :

  • หากวัตถุนั้นมีการเริ่มต้นที่ไม่ว่างเปล่าการเริ่มต้นนั้นจะเสร็จสมบูรณ์

เนื่องจากxจะมีการเริ่มต้นว่างโดยคำจำกัดความของ C ++ 17 (แต่ไม่ใช่แบบร่างในปัจจุบัน) อายุการใช้งานของมันจะเริ่มขึ้นแล้วเมื่อมีการเข้าถึงใน initializer ในตัวอย่างที่ให้ไว้ด้านบนและในทั้งสองตัวอย่างไม่มีพฤติกรรมที่ไม่ได้กำหนด เนื่องจากอายุการใช้งานของxใน C ++ 17

ข้อความก่อน C ++ 17 นั้นแตกต่างกันอีกครั้ง แต่มีผลลัพธ์เหมือนกัน


คำถามไม่ได้เกี่ยวกับพฤติกรรมที่ไม่ได้กำหนดเมื่อใช้ค่าไม่แน่นอนซึ่งครอบคลุมในเช่นคำถามต่อไปนี้:


@LanguageLawyer ฉันไม่มั่นใจว่าฉันถูกต้องโดยเฉพาะอย่างยิ่งถ้าไม่มีใครตอบยัง หากคนอื่นจะเห็นด้วยกับฉันที่นี่ฉันอาจยื่นหนึ่งไฟล์ในภายหลัง (หรืออาจจะมีคนอื่นมาก่อนฉัน) แต่ฉันไม่ต้องการที่จะยื่นปัญหาที่ฉันไม่แน่ใจเกี่ยวกับ
วอลนัท

@LanguageLawyer: มันไม่สามารถเป็นปัญหาด้านบรรณาธิการได้หากกระดาษทำงานพูดอย่างไม่ชัดแจ้งว่าเป็นสิ่งที่ผิด
เดวิสเฮอร์ริ่ง

1
คำว่ามีการเปลี่ยนแปลงโดยP1358
xskxzr

1
@xskxzr ถูกต้องและในเวลาเดียวกัน LanguageLawyer ได้ยื่นเรื่องการแก้ไขซึ่งดูเหมือนว่าจะถูกส่งต่อไปยัง CWG เพื่อชี้แจงความตั้งใจ
วอลนัต

1
@ clockw0rk int x ^= x;มีรูปแบบไม่ถูกต้อง คุณสามารถมีคำจำกัดความของตัวแปรด้วย initializer (เช่นint x = x;แม้ว่าจะเป็น UB) หรือคำสั่ง xor assignment expression (เช่นx ^= x;แม้ว่ามันจะเป็น UB ถ้าxเป็นประเภทintเป็นแบบเริ่มต้นและไม่ได้กำหนดไว้ล่วงหน้า) คุณไม่สามารถผสมสองสิ่งนี้เป็นหนึ่งเดียว
วอลนัท

คำตอบ:


8

นี้ถูกเปิดเป็นปัญหาบรรณาธิการ มันถูกส่งต่อไปยัง CWG สำหรับการสนทนา (ภายใน) ประมาณ 24 ชั่วโมงต่อมาบุคคลที่ส่งต่อปัญหาสร้างคำขอดึงซึ่งแก้ไขตัวอย่างเพื่อให้ชัดเจนว่าเป็น UB:

ที่นี่การเริ่มต้นของ \ tcode {x} ที่สองมีพฤติกรรมที่ไม่ได้กำหนดเนื่องจาก initializer เข้าถึงที่สอง \ tcode {x} นอกอายุการใช้งาน \ iref {basic.life}

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

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