[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 นั้นแตกต่างกันอีกครั้ง แต่มีผลลัพธ์เหมือนกัน
คำถามไม่ได้เกี่ยวกับพฤติกรรมที่ไม่ได้กำหนดเมื่อใช้ค่าไม่แน่นอนซึ่งครอบคลุมในเช่นคำถามต่อไปนี้:
int x ^= x;
มีรูปแบบไม่ถูกต้อง คุณสามารถมีคำจำกัดความของตัวแปรด้วย initializer (เช่นint x = x;
แม้ว่าจะเป็น UB) หรือคำสั่ง xor assignment expression (เช่นx ^= x;
แม้ว่ามันจะเป็น UB ถ้าx
เป็นประเภทint
เป็นแบบเริ่มต้นและไม่ได้กำหนดไว้ล่วงหน้า) คุณไม่สามารถผสมสองสิ่งนี้เป็นหนึ่งเดียว