TL; ดร
วิธีเดียวที่คุณสามารถประกาศตัวแปรที่มี intializer หรือวัตถุบางอย่างที่ไม่น่ารำคาญภายในเป็นกรณีคือการแนะนำขอบเขตบล็อกใช้{}
หรือโครงสร้างการควบคุมอื่น ๆ ที่มีขอบเขตของตัวเองเหมือนห่วงหรือถ้ามีคำสั่ง
รายละเอียดที่เต็มไปด้วยเลือด
เราจะเห็นว่ากรณีต่างๆเป็นเพียงข้อความที่มีป้ายกำกับเช่นป้ายกำกับที่ใช้กับคำสั่งgoto ( ครอบคลุมอยู่ในร่างมาตรฐาน C ++ส่วน 6.1 คำสั่งที่มีป้ายกำกับ ) และเราสามารถดูได้จากส่วน6.7
ย่อหน้าที่3ว่าการกระโดดผ่านการประกาศไม่ได้รับอนุญาตในหลาย ๆ กรณี รวมถึงผู้ที่มีการเริ่มต้น:
เป็นไปได้ที่จะถ่ายโอนไปยังบล็อก แต่ไม่ใช่ในลักษณะที่ข้ามการประกาศด้วยการเริ่มต้น โปรแกรมที่กระโดด87จากจุดที่ตัวแปรที่มีระยะเวลาการจัดเก็บอัตโนมัติไม่อยู่ในขอบเขตไปยังจุดที่อยู่ในขอบเขตนั้นมีรูปแบบที่ไม่ถูกต้องเว้นแต่ตัวแปรจะมีประเภทสเกลาร์ประเภทคลาสที่มีตัวสร้างเริ่มต้นเล็กน้อยและตัวทำลายเล็กน้อย เวอร์ชันที่ผ่านการรับรอง CV ของประเภทใดประเภทหนึ่งเหล่านี้หรืออาร์เรย์ของประเภทก่อนหน้านี้และประกาศโดยไม่มีตัวเริ่มต้น (8.5)
และให้ตัวอย่างนี้:
void f() {
// ...
goto lx; // ill-formed: jump into scope of a
ly:
X a = 1;
// ...
lx:
goto ly; // OK, jump implies destructor
// call for a followed by construction
// again immediately following label ly
}
หมายเหตุมีรายละเอียดปลีกย่อยบางอย่างที่นี่คุณได้รับอนุญาตให้ข้ามผ่านการประกาศสเกลาร์ที่ไม่มีการกำหนดค่าเริ่มต้นตัวอย่างเช่น:
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
ถูกต้องสมบูรณ์ ( ตัวอย่างสด ) แน่นอนว่าหากคุณต้องการประกาศตัวแปรเดียวกันในแต่ละกรณีพวกเขาแต่ละคนจะต้องมีขอบเขตของตัวเอง แต่มันก็ทำงานในลักษณะเดียวกันนอกเหนือจากคำสั่งสวิตช์เช่นกันดังนั้นจึงไม่ควรแปลกใจมาก
สำหรับเหตุผลในการไม่อนุญาตให้ข้ามการเริ่มต้นที่ผ่านมารายงานข้อบกพร่อง 467แม้ว่าจะครอบคลุมประเด็นที่แตกต่างกันเล็กน้อยก็มีกรณีที่สมเหตุสมผลสำหรับตัวแปรอัตโนมัติ :
[... ] ตัวแปรอัตโนมัติหากไม่ได้กำหนดค่าเริ่มต้นอย่างชัดเจนอาจมีค่าที่ไม่แน่นอน ("ขยะ") รวมถึงการแทนกับดัก [... ]
อาจเป็นเรื่องที่น่าสนใจกว่าที่จะดูกรณีที่คุณขยายขอบเขตภายในการสลับไปมาหลาย ๆกรณีตัวอย่างที่มีชื่อเสียงที่สุดของสิ่งนี้น่าจะเป็นอุปกรณ์ของ Duffซึ่งจะมีลักษณะดังนี้:
void send( int *to, const int *from, int count)
{
int n = (count + 7) / 8;
switch(count % 8)
{
case 0: do { *to = *from++; // <- Scope start
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n > 0); // <- Scope end
}
}