Trước khi bạn bắt đầu la hét hành vi không xác định, điều này được liệt kê rõ ràng trong N4659 (C ++ 17)
i = i++ + 1; // the value of i is incremented
Tuy nhiên, trong N3337 (C ++ 11)
i = i++ + 1; // the behavior is undefined
Những gì đã thay đổi?
Từ những gì tôi có thể thu thập, từ [N4659 basic.exec]
Trừ khi có ghi chú, các đánh giá toán hạng của các toán tử riêng lẻ và các biểu thức con của các biểu thức riêng lẻ đều không được đưa ra. [...] Các tính toán giá trị của các toán hạng của 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 tác dụng phụ trên một vị trí bộ nhớ không bị ảnh hưởng so với tác dụng phụ khác trên cùng một vị trí bộ nhớ hoặc tính toán giá trị sử dụng giá trị của bất kỳ đối tượng nào trong cùng một vị trí bộ nhớ và chúng không có khả năng đồng thời, thì hành vi không được xác định.
Trong đó giá trị được xác định tại [N4659 basic.type]
Đối với các loại có thể sao chép tầm thường, biểu diễn giá trị là một tập hợp các bit trong biểu diễn đối tượng xác định một giá trị , là một phần tử riêng biệt của một tập hợp các giá trị được xác định theo thực hiện
Trừ khi có ghi chú, các đánh giá toán hạng của các toán tử riêng lẻ và các biểu thức con của các biểu thức riêng lẻ đều không được đưa ra. [...] Các tính toán giá trị của các toán hạng của 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 tác dụng phụ trên một đối tượng vô hướng không có kết quả tương ứng 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 tính toán giá trị sử dụng giá trị của cùng một đối tượng vô hướng, thì hành vi không được xác định.
Tương tự, giá trị được xác định tại [N3337 basic.type]
Đối với các loại có thể sao chép tầm thường, biểu diễn giá trị là một tập hợp các bit trong biểu diễn đối tượng xác định một giá trị , là một phần tử riêng biệt của một tập hợp các giá trị được xác định theo thực hiện.
Chúng giống hệt nhau ngoại trừ đề cập đến đồng thời không quan trọng và với việc sử dụng vị trí bộ nhớ thay vì đối tượng vô hướng , trong đó
Các kiểu số học, kiểu liệt kê, kiểu con trỏ, kiểu con trỏ đến kiểu thành viên
std::nullptr_t
và các phiên bản đủ điều kiện cv của các loại này được gọi chung là kiểu vô hướng.
Mà không ảnh hưởng đến ví dụ.
Toán tử gán (=) và toán tử gán gán tổng hợp tất cả các nhóm từ phải sang trái. Tất cả đều yêu cầu một giá trị có thể sửa đổi là toán hạng bên trái của chúng và trả về một giá trị tham chiếu đến toán hạng bên trái. Kết quả trong mọi trường hợp là trường bit nếu toán hạng bên trái là trường bit. Trong mọi trường hợp, phép gán được sắp xếp theo trình tự sau khi tính toán giá trị của toán hạng phải và trái và trước khi tính toán giá trị của biểu thức gán. Toán hạng bên phải được sắp xếp theo thứ tự trước toán hạng bên trái.
Toán tử gán (=) và toán tử gán gán tổng hợp tất cả các nhóm từ phải sang trái. Tất cả đều yêu cầu một giá trị có thể sửa đổi là toán hạng bên trái của chúng và trả về một giá trị tham chiếu đến toán hạng bên trái. Kết quả trong mọi trường hợp là trường bit nếu toán hạng bên trái là trường bit. Trong mọi trường hợp, phép gán được sắp xếp theo trình tự sau khi tính toán giá trị của toán hạng phải và trái và trước khi tính toán giá trị của biểu thức gán.
Sự khác biệt duy nhất là câu cuối cùng vắng mặt trong N3337.
Tuy nhiên, câu cuối cùng không nên có bất kỳ tầm quan trọng nào vì toán hạng bên trái i
không phải là "hiệu ứng phụ khác" hay "sử dụng giá trị của cùng một đối tượng vô hướng" vì biểu thức id là một giá trị.
i = i++ + 1;
.