Hãy viết lại mã của bạn như
E1 = (E2 = E3)
nơi E1 là sự biểu hiện a
, E2 là sự biểu hiện a += 1
và E3 là sự biểu hiện 10
. Ở đây chúng ta đã sử dụng, toán tử gán nhóm từ phải sang trái (§5.17/1 trong C++ 11 Standard).
§5.17/1 hơn nữa khẳng định:
Trong mọi trường hợp, việc chuyển nhượng được lập trình tự sau khi tính toán giá trị của quyền và trái toán hạng, và trước khi tính toán giá trị của biểu thức chuyển nhượng.
Áp dụng điều này vào biểu thức của chúng tôi có nghĩa là trước tiên chúng tôi phải đánh giá các biểu thức con E1
và E2 = E3
. Lưu ý rằng không có mối quan hệ "được sắp xếp trước" giữa hai đánh giá này, nhưng điều đó không gây ra vấn đề gì.
Việc đánh giá biểu thức id E1
là không đáng kể (kết quả là a
chính nó). Việc đánh giá biểu thức chuyển nhượng biểu thức chuyển nhượngE2 = E3
như sau:
Đầu tiên cả hai biểu thức con phải được đánh giá. Việc đánh giá nghĩa đenE3
là một lần nữa tầm thường (cung cấp giá trị gia tăng của giá trị 10).
Việc thẩm định (hợp chất) nhượng thể hiệnE2
được thực hiện theo các bước sau:
1) Hành vi của a += 1
tương đương với a = a + 1
nhưng a
chỉ được đánh giá một lần (§5.17/7) . Sau khi đánh giá các biểu thức con a
và 1
(theo thứ tự tùy ý), một chuyển đổi lvalue-to-rvalue được áp dụng cho a
để đọc giá trị được lưu trữ trong a
.
2) Các giá trị của a
(đó là 0
) và 1
được thêm vào (a + 1
) và kết quả bổ sung này là một prvalue giá trị 1
.
3) Trước khi chúng tôi có thể tính toán kết quả của nhiệm vụ a = a + 1
giá trị của đối tượng toán hạng bên trái đề cập đến được thay thế bằng giá trị của toán hạng bên phải (§5.17/2). Kết quả của E2
sau đó là một định giá trị bằng lvalue cho giá trị mới 1
.Lưu ý rằng tác dụng phụ (cập nhật giá trị của toán hạng bên trái) được giải trình tự trước khi tính toán giá trị của biểu thức gán. Đây là §5.17/1 được trích dẫn ở trên.
Bây giờ chúng ta đã đánh giá subexpressions E2
và E3
, giá trị của biểu thức E2
đề cập đến được thay thế bằng giá trị của E3
, đó là 10
. Do đó kết quả của E2 = E3
là một giá trị của giá trị 10
.
Cuối cùng, biểu thức giá trị E1
đề cập đến được thay thế bằng giá trị của biểu thức E2 = E3
, mà chúng tôi đã tính là 10
. Do đó, biến số a
kết thúc để chứa giá trị 10
.
Vì tất cả các bước này được xác định rõ, toàn bộ biểu thức mang lại giá trị được xác định rõ.
Lưu ý phụ: Kiểm tra kết quả của biểu thức có thể không xác định không cho chúng tôi biết đó có thực sự là UB hay không. Nó có thể là UB và tạo ra kết quả chính xác. – jrok
@jrok đó là mã mẫu, có lẽ ngay cả một SSCCE, vì SO yêu cầu tôi phải * bao gồm mã hợp lệ *. Tôi đã thử kiểm tra nó, chỉ vì tò mò, nhưng tôi nhận ra nó không chứng minh gì; do đó tôi thậm chí không đề cập đến nó. – Dariusz
@jrok - nó có thể tạo ra kết quả "chính xác". Các dấu ngoặc kép rất quan trọng. '' –