Đầu tiên:
Một do-while
vòng lặp là không giống như một while
-loop hoặc một for
-loop.
while
và for
các vòng lặp có thể không chạy phần thân của vòng lặp.
- Một
do-while
vòng lặp luôn chạy thân vòng lặp ít nhất một lần - nó bỏ qua việc kiểm tra điều kiện ban đầu.
Vì vậy, đó là sự khác biệt hợp lý. Nói như vậy nhưng không phải ai cũng tuân thủ nghiêm ngặt điều này. Vòng lặp for while
hoặc for
được sử dụng khá phổ biến ngay cả khi nó được đảm bảo rằng nó sẽ luôn lặp lại ít nhất một lần. (Đặc biệt là trong các ngôn ngữ có vòng lặp foreach .)
Vì vậy, để tránh so sánh táo và cam, tôi sẽ tiếp tục giả sử rằng vòng lặp sẽ luôn chạy ít nhất một lần. Hơn nữa, tôi sẽ không đề cập for
lại các vòng lặp vì chúng về cơ bản là while
các vòng lặp với một chút đường cú pháp cho bộ đếm vòng lặp.
Vì vậy, tôi sẽ trả lời câu hỏi:
Nếu một while
vòng lặp được đảm bảo lặp lại ít nhất một lần, thì liệu có tăng hiệu suất nào khi sử dụng một do-while
vòng lặp thay thế không.
A do-while
bỏ qua kiểm tra điều kiện đầu tiên. Vì vậy, có một nhánh ít hơn và một điều kiện ít hơn để đánh giá.
Nếu điều kiện đắt để kiểm tra và bạn biết mình được đảm bảo lặp lại ít nhất một lần, thì một do-while
vòng lặp có thể nhanh hơn.
Và mặc dù đây được coi là một tối ưu hóa vi mô tốt nhất, nhưng nó là một điều mà trình biên dịch không phải lúc nào cũng làm được: Cụ thể là khi trình biên dịch không thể chứng minh rằng vòng lặp sẽ luôn nhập ít nhất một lần.
Nói cách khác, một vòng lặp while:
while (condition){
body
}
Hiệu quả giống như sau:
if (condition){
do{
body
}while (condition);
}
Nếu bạn biết rằng bạn sẽ luôn lặp lại ít nhất một lần, thì câu lệnh if đó không liên quan.
Tương tự như vậy ở cấp độ lắp ráp, đây là cách các vòng lặp khác nhau biên dịch thành:
vòng lặp do-while:
start:
body
test
conditional jump to start
trong khi lặp lại:
test
conditional jump to end
start:
body
test
conditional jump to start
end:
Lưu ý rằng điều kiện đã được nhân đôi. Một cách tiếp cận thay thế là:
unconditional jump to end
start:
body
end:
test
conditional jump to start
... loại bỏ mã trùng lặp để có thêm một bước nhảy.
Dù bằng cách nào, nó vẫn tệ hơn một do-while
vòng lặp bình thường .
Điều đó nói rằng, trình biên dịch có thể làm những gì họ muốn. Và nếu họ có thể chứng minh rằng vòng lặp luôn đi vào một lần, thì nó đã hoàn thành công việc cho bạn.
Nhưng mọi thứ hơi kỳ lạ đối với ví dụ cụ thể trong câu hỏi vì nó có phần thân vòng lặp trống. Vì không có cơ thể, không có sự khác biệt hợp lý giữa while
và do-while
.
FWIW, tôi đã kiểm tra điều này trong Visual Studio 2012:
Với phần thân trống, nó thực sự tạo ra cùng một mã cho while
và do-while
. Vì vậy, phần đó có thể là một phần còn lại của ngày xưa khi các trình biên dịch không tuyệt vời như vậy.
Nhưng với phần thân không trống, VS2012 quản lý để tránh trùng lặp mã điều kiện, nhưng vẫn tạo thêm một bước nhảy có điều kiện.
Vì vậy, thật mỉa mai rằng trong khi ví dụ trong câu hỏi nêu bật lý do tại sao một do-while
vòng lặp có thể nhanh hơn trong trường hợp chung, bản thân ví dụ này dường như không mang lại bất kỳ lợi ích nào trên một trình biên dịch hiện đại.
Xem xét mức độ cũ của nhận xét, chúng tôi chỉ có thể đoán tại sao nó lại quan trọng. Rất có thể các trình biên dịch vào thời điểm đó không có khả năng nhận ra rằng phần thân trống. (Hoặc nếu có, họ đã không sử dụng thông tin.)