Sự khác biệt là ++a
là một giá trị, tuy nhiên a++
thì không. Đây được xác định bởi C++ 14 [expr.pre.incr]/1:
Các toán hạng của tiền tố ++
được sửa đổi bằng cách thêm 1 [...] Các toán hạng phải là một giá trị trái sửa đổi. [...] Kết quả là toán hạng được cập nhật; đó là một giá trị trái
và [expr.post.incr]/1:
[...] Kết quả là một prvalue.
Bây giờ chúng ta xem xét auto && b = ++a;
. ++a
là một lvalue. auto&&
là tham chiếu chuyển tiếp. Tham chiếu chuyển tiếp thực sự có thể liên kết với các giá trị: auto
có thể tự suy ra một loại tham chiếu. Mã này khấu trừ thành int &b = ++a;
.
Khi tham chiếu được liên kết với một giá trị cùng loại, tham chiếu sẽ liên kết trực tiếp, vì vậy b
sẽ trở thành một tên khác cho a
.
Trong ví dụ thứ hai, là giá trị chính xác. Điều này có nghĩa là nó không có địa chỉ liên quan và nó không còn liên quan đến biến số a
. Dòng này có cùng một hành vi như ++a; auto && b = (a + 0);
.
Thứ nhất, kể từ a++
là giá trị gia tăng, auto&&
khấu trừ thành int&&
. (ví dụ: auto
khấu trừ thành int
). Khi một tham chiếu của loại không phải lớp được ràng buộc với một giá trị, một đối tượng tạm thời được sao chép-khởi tạo từ giá trị. Đối tượng này đã kéo dài tuổi thọ của nó để khớp với tham chiếu.
Vì vậy, b
trong trường hợp thứ hai được liên kết với một đối tượng khác từ a
, int "tạm thời" (không thực sự quá tạm thời, vì nó kéo dài miễn là b
).
Quy tắc ràng buộc tham chiếu nằm trong [dcl.init.ref].
Nguồn
2016-02-10 13:10:51
Tôi sẽ cung cấp cho bạn một gợi ý - 'a' không phải là một giá trị. – erip
@erip Vâng, tôi biết, nhưng sự khác biệt trong hai ví dụ cho 'b' là gì? – vladon
Trong ví dụ thứ hai 'b' nhận giá trị' a' mà không tăng giá trị trước đó, như trong ví dụ đầu tiên. – x13