TL; DR
Cách duy nhất bạn có thể khai báo một biến với intializer hoặc một số đối tượng không tầm thường bên trong một trường hợp là sử dụng phạm vi khối bằng cách sử dụng {}
hoặc cấu trúc điều khiển khác có phạm vi riêng của nó như một vòng lặp hoặc câu lệnh if .
Chi tiết về máu
Chúng ta có thể thấy rằng trường hợp chỉ là báo cáo được dán nhãn như nhãn sử dụng với một goto statement ( này được bao phủ trong C ++ dự thảo tiêu chuẩn phần 6.1 tuyên bố đã được gán nhãn ) và chúng ta có thể nhìn thấy từ phần 6.7
đoạn 3 mà nhảy qua một tuyên bố không được phép trong nhiều trường hợp , bao gồm những thứ có khởi tạo:
Có thể chuyển vào một khối, nhưng không phải theo cách bỏ qua khai báo với khởi tạo. Chương trình nhảy 87 từ một điểm mà một biến có thời lượng lưu trữ tự động không nằm trong phạm vi đến một điểm mà nó trong phạm vi không được định hình trừ khi biến có kiểu vô hướng, kiểu lớp với một hàm tạo mặc định tầm thường và một hàm hủy tầm thường, phiên bản đủ điều kiện cv của một trong các kiểu này hoặc một mảng của một trong các kiểu trước đó và được khai báo mà không có trình khởi tạo (8.5).
và cung cấp ví dụ này:
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
}
Lưu ý, có một số điều tinh tế ở đây, bạn được phép lướt qua một khai báo vô hướng không có phần khởi tạo, ví dụ:
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
là hoàn toàn hợp lệ ( ví dụ trực tiếp ). Tất nhiên nếu bạn muốn khai báo cùng một biến trong mỗi trường hợp thì chúng sẽ cần phạm vi riêng của chúng nhưng nó hoạt động theo cùng một cách bên ngoài các câu lệnh switch , vì vậy đó không phải là một bất ngờ lớn.
Về lý do không cho phép khởi tạo quá khứ nhảy, báo cáo lỗi 467 mặc dù bao gồm một vấn đề hơi khác nhưng cung cấp một trường hợp hợp lý cho các biến tự động :
[...] các biến tự động, nếu không được khởi tạo rõ ràng, có thể có các giá trị không xác định ("rác"), bao gồm các biểu diễn bẫy, [...]
Có lẽ sẽ thú vị hơn khi xem xét trường hợp bạn mở rộng phạm vi trong một công tắc qua nhiều trường hợp , ví dụ nổi tiếng nhất về điều này có lẽ là thiết bị của Duff trông giống như sau:
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
}
}