Nếu chúng ta có ba hàm (foo, bar và baz) được cấu tạo như vậy ...
foo(bar(), baz())
Có đảm bảo nào theo tiêu chuẩn C ++ rằng thanh sẽ được đánh giá trước baz không?
Nếu chúng ta có ba hàm (foo, bar và baz) được cấu tạo như vậy ...
foo(bar(), baz())
Có đảm bảo nào theo tiêu chuẩn C ++ rằng thanh sẽ được đánh giá trước baz không?
Câu trả lời:
Không, không có gì đảm bảo. Nó không xác định theo tiêu chuẩn C ++.
Bjarne Stroustrup cũng nói rõ điều đó trong phần 6.2.2 của "Ngôn ngữ lập trình C ++" phiên bản thứ 3, với một số lý do:
Mã tốt hơn có thể được tạo ra mà không có hạn chế về thứ tự đánh giá biểu thức
Mặc dù về mặt kỹ thuật, điều này đề cập đến một phần trước đó của cùng một phần nói rằng thứ tự đánh giá các phần của một biểu thức cũng không được xác định, tức là
int x = f(2) + g(3); // unspecified whether f() or g() is called first
Không có thứ tự cụ thể nào cho bar () và baz () - điều duy nhất mà Tiêu chuẩn nói là cả hai đều sẽ được đánh giá trước khi foo () được gọi. Từ Tiêu chuẩn C ++, phần 5.2.2 / 8:
Thứ tự đánh giá các lập luận là không xác định.
bar
, rồi dòng 1 baz
, rồi dòng 2 bar
, v.v.), điều này cũng rất hay. :-)
Từ [5.2.2] Cuộc gọi hàm,
Thứ tự đánh giá các lập luận là không xác định. Tất cả các hiệu ứng phụ của đánh giá biểu thức đối số có hiệu lực trước khi hàm được nhập.
Do đó, không có gì đảm bảo rằng nó bar()
sẽ chạy trước đó baz()
, chỉ có điều đó bar()
và baz()
sẽ được gọi trước đó foo
.
Cũng lưu ý từ [5] Biểu thức rằng:
ngoại trừ khi được lưu ý [ví dụ: các quy tắc đặc biệt cho
&&
và||
], thứ tự đánh giá toán hạng của các toán tử riêng lẻ và biểu thức con của các biểu thức riêng lẻ, và thứ tự diễn ra các tác dụng phụ, là không xác định.
vì vậy ngay cả khi bạn đang đặt câu hỏi liệu bar()
sẽ chạy trước khi baz()
vào foo(bar() + baz())
, thứ tự là vẫn chưa được xác định.
&
, &&
đảm bảo đánh giá từ trái sang phải: toán hạng thứ hai không được đánh giá nếu toán hạng đầu tiên là false
."
C ++ 17 chỉ định thứ tự đánh giá cho các toán tử chưa được chỉ định cho đến C ++ 17. Xem câu hỏi Các đảm bảo thứ tự đánh giá được giới thiệu bởi C ++ 17 là gì? Nhưng lưu ý biểu hiện của bạn
foo(bar(), baz())
vẫn chưa xác định thứ tự đánh giá.
Trong C ++ 11, văn bản liên quan có thể được tìm thấy trong 8.3.6 Đối số mặc định / 9 (Mỏ nhấn mạnh)
Các đối số mặc định được đánh giá mỗi khi hàm được gọi. Thứ tự đánh giá của các đối số hàm là không xác định . Do đó, các tham số của một hàm sẽ không được sử dụng trong một đối số mặc định, ngay cả khi chúng không được đánh giá.
Xung quanh tương tự cũng được sử dụng bởi tiêu chuẩn C ++ 14 và được tìm thấy trong cùng một phần .
Như những người khác đã chỉ ra, tiêu chuẩn không đưa ra bất kỳ hướng dẫn nào về trình tự đánh giá cho tình huống cụ thể này. Thứ tự đánh giá này sau đó được để lại cho trình biên dịch và trình biên dịch có thể có một đảm bảo.
Điều quan trọng cần nhớ là tiêu chuẩn C ++ thực sự là một ngôn ngữ để hướng dẫn trình biên dịch về việc xây dựng assembly / mã máy. Tiêu chuẩn chỉ là một phần của phương trình. Trường hợp tiêu chuẩn không rõ ràng hoặc được xác định cụ thể việc triển khai, bạn nên chuyển sang trình biên dịch và hiểu cách nó dịch các lệnh C ++ thành ngôn ngữ máy thực sự.
Vì vậy, nếu thứ tự đánh giá là một yêu cầu, hoặc ít nhất là quan trọng và việc tương thích với nhiều trình biên dịch không phải là một yêu cầu, hãy điều tra xem cuối cùng trình biên dịch của bạn sẽ kết hợp điều này như thế nào, câu trả lời của bạn cuối cùng có thể nằm ở đó. Lưu ý rằng trình biên dịch có thể thay đổi phương pháp của nó trong tương lai