Cập nhật, xem bên dưới!
Tôi đã nghe và đọc rằng C ++ 0x cho phép trình biên dịch in "Xin chào" cho đoạn trích sau
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
Nó rõ ràng có một cái gì đó để làm với chủ đề và khả năng tối ưu hóa. Dường như với tôi rằng điều này có thể làm nhiều người ngạc nhiên.
Có ai có một lời giải thích tốt về lý do tại sao điều này là cần thiết để cho phép? Để tham khảo, bản nháp C ++ 0x gần đây nhất cho biết tại6.5/5
Một vòng lặp, bên ngoài câu lệnh for-init trong trường hợp câu lệnh for,
- không thực hiện cuộc gọi đến các chức năng I / O của thư viện và
- không truy cập hoặc sửa đổi các đối tượng dễ bay hơi và
- thực hiện không có hoạt động đồng bộ hóa (1.10) hoặc hoạt động nguyên tử (Điều 29)
có thể được giả định bởi việc thực hiện để chấm dứt. [Lưu ý: Điều này nhằm cho phép chuyển đổi trình biên dịch, chẳng hạn như loại bỏ các vòng lặp trống, ngay cả khi việc chấm dứt không thể được chứng minh. - lưu ý cuối]
Biên tập:
Bài viết sâu sắc này nói về văn bản Tiêu chuẩn đó
Thật không may, các từ "hành vi không xác định" không được sử dụng. Tuy nhiên, bất cứ lúc nào tiêu chuẩn nói "trình biên dịch có thể giả sử P", điều đó ngụ ý rằng một chương trình có thuộc tính không-P có ngữ nghĩa không xác định.
Điều đó có đúng không, và trình biên dịch có được phép in "Tạm biệt" cho chương trình trên không?
Có một chủ đề thậm chí sâu sắc hơn ở đây , đó là về một sự thay đổi tương tự với C, được bắt đầu bởi Guy đã thực hiện bài viết được liên kết ở trên. Trong số các sự kiện hữu ích khác, họ đưa ra một giải pháp dường như cũng áp dụng cho C ++ 0x ( Cập nhật : Điều này sẽ không hoạt động nữa với n3225 - xem bên dưới!)
endless:
goto endless;
Một trình biên dịch không được phép tối ưu hóa điều đó, dường như, bởi vì đó không phải là một vòng lặp, mà là một bước nhảy. Một anh chàng khác tóm tắt sự thay đổi được đề xuất trong C ++ 0x và C201X
Bằng cách viết một vòng lặp, các lập trình viên đang khẳng định một trong hai mà vòng lặp làm điều gì đó với hành vi có thể nhìn thấy (Thực hiện I / O, truy cập đối tượng không ổn định, hoặc thực hiện đồng bộ hoặc các hoạt động nguyên tử), hoặc rằng nó cuối cùng chấm dứt. Nếu tôi vi phạm giả định đó bằng cách viết một vòng lặp vô hạn không có tác dụng phụ, tôi đang nói dối với trình biên dịch và hành vi của chương trình của tôi không được xác định. (Nếu tôi may mắn, trình biên dịch có thể cảnh báo tôi về điều đó.) Ngôn ngữ không cung cấp (không còn cung cấp?) Một cách để thể hiện một vòng lặp vô hạn mà không có hành vi có thể nhìn thấy.
Cập nhật ngày 3.1.2011 với n3225: Ủy ban đã chuyển văn bản thành 1.10 / 24 và nói
Việc thực hiện có thể cho rằng bất kỳ luồng nào cuối cùng cũng sẽ thực hiện một trong các thao tác sau:
- chấm dứt,
- thực hiện cuộc gọi đến chức năng I / O của thư viện
- truy cập hoặc sửa đổi một đối tượng dễ bay hơi, hoặc
- thực hiện một hoạt động đồng bộ hóa hoặc một hoạt động nguyên tử.
Thủ goto
thuật sẽ không hoạt động nữa!
int x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
thành for(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
? Hoặc có thể theo cách khác, với x
việc được khởi tạo 2
trước vòng lặp. Nó có thể cho biết do_something
không quan tâm đến giá trị của nó x
, vì vậy nó là một tối ưu hóa hoàn toàn an toàn, nếu do_something
không khiến giá trị i
thay đổi sao cho bạn kết thúc trong một vòng lặp vô hạn.
main() { start_daemon_thread(); while(1) { sleep(1000); } }
có thể thoát ngay lập tức thay vì chạy daemon của tôi trong một luồng nền?
while(1) { MyMysteriousFunction(); }
phải được biên dịch độc lập mà không biết định nghĩa của hàm bí ẩn đó, phải không? Vậy làm thế nào chúng ta có thể xác định nếu nó thực hiện cuộc gọi đến bất kỳ chức năng I / O thư viện nào? Nói cách khác: chắc chắn rằng viên đạn đầu tiên có thể được thực hiện khiến không có cuộc gọi nào đến chức năng .