Tôi nghĩ rằng phần này của tiêu chuẩn dự thảo về trình tự đánh giá là có liên quan:
1.9 Thực thi chương trình
...
- Trừ khi được lưu ý, các đánh giá về 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ẻ là không có câu trả lời. Các phép tính giá trị của các toán hạng của một toán tử được sắp xếp theo trình tự trước khi tính toán giá trị của kết quả của toán tử. Nếu một hiệu ứng phụ trên một đối tượng vô hướng là không có hàng rào so với một tác dụng phụ khác trên cùng một đối tượng vô hướng hoặc một phép tính giá trị sử dụng giá trị của cùng một đối tượng vô hướng và chúng không có khả năng xảy ra đồng thời, thì hành vi đó là không xác định
và cả:
5.2.2 Lệnh gọi hàm
...
- [Lưu ý: Các đánh giá của biểu thức hậu tố và của các đối số là tất cả các đánh giá có liên quan đến nhau. Tất cả các tác dụng phụ của đánh giá đối số được giải trình tự trước khi hàm được nhập - ghi chú cuối]
Vì vậy, đối với dòng của bạn c.meth1(&nu).meth2(nu);
, hãy xem xét điều gì đang xảy ra trong toán tử về mặt toán tử gọi hàm cho lần gọi cuối cùng meth2
, vì vậy chúng tôi thấy rõ ràng phân tích thành biểu thức hậu tố và đối số nu
:
operator()(c.meth1(&nu).meth2, nu);
Các đánh giá của biểu thức hậu tố và đối số cho lời gọi hàm cuối cùng (tức là biểu thức hậu tố c.meth1(&nu).meth2
và nu
) là không có câu trả lời liên quan đến nhau theo quy tắc gọi hàm ở trên. Do đó, tác dụng phụ của việc tính toán biểu thức hậu tố trên đối tượng vô hướng là vô hướng ar
liên quan đến đánh giá đối số nu
trước khi meth2
gọi hàm. Theo quy tắc thực thi chương trình ở trên, đây là hành vi không xác định.
Nói cách khác, không có yêu cầu nào đối với trình biên dịch để đánh giá nu
đối số cho lệnh meth2
gọi sau lệnh meth1
gọi - có thể tự do giả định rằng không có tác dụng phụ nào meth1
ảnh hưởng đến việc nu
đánh giá.
Mã hợp ngữ được tạo ra ở trên chứa trình tự sau trong main
hàm:
- Biến
nu
được cấp phát trên ngăn xếp và được khởi tạo bằng 0.
- Một sổ đăng ký (
ebx
trong trường hợp của tôi) nhận được một bản sao giá trị củanu
- Địa chỉ của
nu
và c
được tải vào thanh ghi tham số
meth1
được gọi là
- Thanh ghi giá trị trả về và các giá trị được lưu trữ trước đó của
nu
trong ebx
sổ đăng ký được nạp vào thanh ghi thông số
meth2
được gọi là
Đặc biệt, trong bước 5 ở trên, trình biên dịch cho phép nu
sử dụng lại giá trị được lưu trong bộ nhớ cache của bước 2 trong lệnh gọi hàm tới meth2
. Ở đây, nó không tính đến khả năng nu
có thể đã bị thay đổi bởi lệnh gọi meth1
- 'hành vi không xác định' đang hoạt động.
LƯU Ý: Câu trả lời này đã thay đổi về chất so với dạng ban đầu. Lời giải thích ban đầu của tôi về tác dụng phụ của việc tính toán toán hạng không được giải trình tự trước khi gọi hàm cuối cùng là không chính xác, bởi vì chúng đúng như vậy. Vấn đề là thực tế là việc tính toán các toán hạng được giải trình tự không xác định.