2012-07-03 33 views
12

Hãy nói rằng tôi có một số mã C++:Tại sao C++ thực thi hành vi đó trong quá trình khởi tạo chéo?

if (error) 
    goto exit; 
... 
// size_t i = 0; //error 
size_t i; 
i = 0; 
... 
exit: 
    ... 

Tôi hiểu chúng ta không nên sử dụng goto, nhưng vẫn còn tại sao

size_t i; 
i = 0; 

biên dịch trong khi size_t i = 0; không?

Tại sao hành vi này được thực thi theo tiêu chuẩn (được đề cập bởi @SingerOfTheFall)?

Có thể chuyển thành một khối, nhưng không phải theo cách mà bỏ qua các khai báo có khởi tạo. Một chương trình nhảy từ một điểm trong đó một biến cục bộ có thời lượng lưu trữ tự động không nằm trong phạm vi đến một điểm mà phạm vi đó không đúng định dạng trừ khi biến số có loại POD (3.9) và được khai báo không có bộ khởi tạo.

+0

Trình biên dịch nào? –

+0

@Adriano: g ++ 4.1.1 –

+0

Đã thêm 'language-design' vì bạn đang hỏi về lý do cơ bản cho các quyết định thiết kế cho một ngôn ngữ. – Kos

Trả lời

12

Bạn không thể nhảy qua khởi tạo đối tượng.

size_t i = 0; 

là một khởi, trong khi

size_t i; 
i = 0; 

thì không. C++ Standart nói:

Có thể chuyển thành một khối, nhưng không theo cách mà bỏ qua các khai báo với khởi tạo. Một chương trình nhảy từ một điểm mà một biến cục bộ với thời gian lưu trữ tự động không nằm trong phạm vi đến điểm mà nó nằm trong phạm vi bị hình thành sai trừ khi biến có kiểu POD (3.9) và được khai báo không có bộ khởi tạo.

+3

Bạn có thể giải thích tại sao có một hành vi khác khi chúng có chức năng tương đương? Ý tôi là lý do đằng sau tiêu chuẩn này là gì. –

+0

Khi bạn khởi tạo một biến như thế này, nó vẫn nằm trong phạm vi ngay cả sau khi nhảy. Điều đó có thể gây ra rắc rối lớn nếu bạn sẽ cố gắng truy cập nó, và thậm chí nhiều rắc rối hơn vào cuối phạm vi mà nó sẽ bị phá hủy. Nếu bạn đã nhảy qua, biến không bao giờ tồn tại, và cố gắng để tiêu diệt nó sẽ dẫn đến một vụ tai nạn (có lẽ segfault, tôi không chắc chắn). – SingerOfTheFall

+13

Lý do là trong trường hợp 'int i;', bằng cách xác định biến không có bộ khởi tạo, bạn đang nói "Tôi sẽ chịu trách nhiệm đảm bảo rằng biến được viết trước khi nó được đọc". Ngôn ngữ cho phép bạn thử điều đó và nếu mã sau 'thoát' sử dụng' i', thì bạn đã thất bại. Trong trường hợp của 'int i = 0;', ngôn ngữ thực thi bất kỳ biến nào với bộ khởi tạo là * luôn luôn * được khởi tạo trước khi sử dụng (miễn là bạn không sử dụng nó trong bộ khởi tạo của chính nó). Cách đơn giản duy nhất mà ngôn ngữ có thể thực thi đó là cấm 'goto' của bạn. –

0

Lý do cho quy tắc là nhảy qua khởi tạo để đối tượng ở trạng thái chưa được xác định. Khi bạn kết thúc hàm, hủy các đối tượng chưa được khởi tạo đó có thể không hoạt động.

Một ngoại lệ rõ ràng là

int i; 

rời int uninitialized anyway, do đó bỏ qua đó chỉ là một nửa xấu.

Nếu bạn muốn sớm có chức năng, hãy nhanh chóng return là một tùy chọn để tránh goto.

Các vấn đề liên quan