Rvalues są tym, co można uzyskać z wyrażeń (użytecznego uproszczenia pobranej od standardu C, ale nie sformułowane w języku C++ standardese). Wartości L są "wartościami lokalizatora". Wartości L można stosować jako wartości r. Odnośniki są zawsze wartościami l, nawet jeśli const.
Najważniejszą różnicę, o której musisz wiedzieć, można skondensować do jednego elementu: nie można przyjąć adresu wartości rwart (ponownie, nie jest to standardowe, ale użyteczne uogólnienie reguł). Lub, mówiąc inaczej, nie możesz ustalić dokładnej lokalizacji dla wartości rvalue —, jeśli mógłbyś, to masz wartość lvalue. (Możesz jednak związać stałą o wartości &, aby "naprawić ją na miejscu", a 0x bardzo drastycznie zmieniła reguły.)
Zdefiniowane przez użytkownika typy (UDT) są jednak nieco wyjątkowe: można przekonwertować dowolny rvalue do lwartością, jeśli klasa interfejs pozwala go:
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)
}
Coś podobnego dzieje się za A() = a
, z wyjątkiem przez operatora przypisania kompilatora dostarczone, aby włączyć rvalue A()
do *this
. Zacytować standard, 12,8/10:
Jeżeli definicja klasy nie jawnie zadeklarować operatora przypisania kopia, jeden jest zadeklarowana niejawnie. Niejawnie zadeklarowanej operator przypisania kopia dla klasy X będzie mieć formę
X& X::operator=(const X&)
A potem to idzie z większą kwalifikacji i widowisko, ale to jest istotne bit tutaj. Ponieważ jest to funkcja członkowska, można ją wywoływać na wartościach r, podobnie jak Special :: get_lvalue może być, tak jakbyś napisał A().operator=(a)
zamiast A() = a
.
Podczas odkrywania jawnie zabronione jest int() = 1
, ponieważ ints nie mają operatora = zaimplementowanego w ten sam sposób. Jednak ta niewielka rozbieżność między typami nie ma znaczenia w praktyce (przynajmniej nie, że znalazłem).
POD oznacza zwykłe stare dane i jest zbiorem wymagań, które określają użycie memcpy, co odpowiada kopiowaniu. Non-POD jest dowolnym typem, którego nie można użyć do kopiowania memcpy (naturalne przeciwieństwo POD, nic nie jest tu ukryte), który zwykle jest typem, który napiszesz w C++. Bycie POD lub non-POD nie zmienia żadnego z powyższych i jest naprawdę oddzielnym problemem.
Specyficzny dla C, ale nadal przydatny dla programistów C++ do zrozumienia: http://stackoverflow.com/questions/2038414/lvalue-and-rvalue/2038427#2038427. (Jest to jedna z dziedzin, w których oba języki zasadniczo się dzielą, mimo że C++ jest nieco bardziej skomplikowana z odniesieniami i faktycznie używa terminu "rvalue", którego C już nie ma). –
"_Or, mówiąc inaczej, nie możesz Napraw dokładną lokalizację dla wartości r "zgodnie ze standardem językowym, wartość rdzenia podstawowego nie jest nawet obiektem i nie ma adresu. – curiousguy