Rvalues là những gì bạn nhận được từ biểu thức (đơn giản hóa hữu ích lấy từ tiêu chuẩn C, nhưng không diễn đạt trong C++ tiêu chuẩn). Giá trị là "giá trị định vị". Các giá trị có thể được sử dụng làm giá trị. Tham chiếu luôn là các giá trị, ngay cả khi const.
Sự khác biệt chính mà bạn phải biết là có thể được cô đặc thành một mục: bạn không thể lấy địa chỉ của một giá trị (một lần nữa, không phải là tiêu chuẩn nhưng là khái quát hóa các quy tắc hữu ích). Hoặc để đặt theo cách khác, bạn không thể sửa một địa điểm chính xác để nhận giá trị — nếu có thể, sau đó bạn sẽ có lvalue. (Tuy nhiên, bạn có thể liên kết một const & với một giá trị để "sửa chữa nó tại chỗ", và 0x đang thay đổi các quy tắc quyết liệt.)
Kiểu do người dùng định nghĩa (UDT), tuy nhiên, hơi đặc biệt: bạn có thể chuyển đổi bất kỳ rvalue vào một giá trị trái, nếu giao diện của lớp cho phép nó:
struct Special {
Special& get_lvalue() { return *this; }
};
void f() {
// remember "Special()" is an rvalue
Special* p = &Special().get_lvalue(); // even though you can't dereference the
// pointer (because the object is destroyed), you still just took the address
// of a temporary
// note that the get_lvalue() method doesn't need to operate on a const
// object (though that would be fine too, if the return type matched)
}
Something tương tự đang xảy ra cho A() = a
của bạn, ngoại trừ thông qua toán tử gán trình biên dịch cung cấp, để biến rvalue A()
vào *this
. Để trích dẫn tiêu chuẩn, 12,8/10:
Nếu định nghĩa lớp không tuyên bố một cách rõ ràng một toán tử gán sao chép, một tuyên bố ngầm. Các ngầm-tuyên bố tử gán bản sao cho một lớp X sẽ có dạng
X& X::operator=(const X&)
Và sau đó nó đi vào với nhiều trình độ và thông số kỹ thuật, nhưng đó là các bit quan trọng ở đây. Vì đó là một hàm thành viên, nó có thể được gọi trên giá trị, giống như Special :: get_lvalue có thể, như thể bạn đã viết A().operator=(a)
thay vì A() = a
.
int() = 1
bị cấm hoàn toàn khi bạn phát hiện ra, vì int không có toán tử = được triển khai theo cùng một cách. Tuy nhiên, sự khác biệt nhỏ giữa các loại không quan trọng trong thực tế (ít nhất là không phải là tôi đã tìm thấy).
POD có nghĩa là Dữ liệu cũ thuần túy và là tập hợp các yêu cầu chỉ định bằng memcpy tương đương với sao chép. Không phải POD là bất kỳ loại nào mà bạn không thể sử dụng memcpy để sao chép (đối diện tự nhiên của POD, không có gì ẩn ở đây), có xu hướng là hầu hết các loại bạn sẽ viết bằng C++. Là POD hoặc không phải POD không thay đổi bất kỳ điều nào ở trên, và thực sự là một vấn đề riêng biệt.
C-cụ thể, nhưng vẫn hữu ích cho các lập trình viên C++ để hiểu: http://stackoverflow.com/questions/2038414/lvalue-and-rvalue/2038427#2038427. (Đây là một khu vực cả hai ngôn ngữ về cơ bản chia sẻ, mặc dù C++ khá phức tạp hơn với các tham chiếu và thực sự sử dụng thuật ngữ "rvalue" mà C không còn nữa.) –
"_Or để đặt nó theo cách khác, bạn không thể sửa chữa một vị trí chính xác cho một rvalue_ "theo tiêu chuẩn ngôn ngữ, một rvalue của loại cơ bản thậm chí không phải là một đối tượng, và không có một địa chỉ. – curiousguy