R-значения - это то, что вы получаете из выражений (полезное упрощение взято из стандарта C, но не сформулировано в стандарте C ++)Lvalues - это «значения локатора».L-значения могут быть использованы как значения.Ссылки всегда являются lvalues, даже если const.
Основное различие, о котором вы должны знать, может быть сведено к одному элементу: вы не можете взять адрес r-значения (опять же, не стандартный, но полезныйобобщение правил).Или, другими словами, вы не можете исправить точное местоположение для r-значения - если бы вы могли, то у вас было бы l-значение .(Однако вы можете привязать const & к r-значению, чтобы «исправить его на месте», а 0x радикально меняет правила.)
Пользовательские типы (UDT), однако, немного особенные: выможет преобразовать любое значение r в значение lvalue, если интерфейс класса позволяет это:
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)
}
Нечто подобное происходит с вашим A() = a
, за исключением того, что с помощью оператора присваивания, предоставленного компилятором, для поворота значения r A()
в *this
.Чтобы процитировать стандарт, 12.8 / 10:
Если определение класса не объявляет явно оператор копирования, одно объявляется неявно .Неявно объявленный оператор присваивания копии для класса X будет иметь форму
X& X::operator=(const X&)
И затем он продолжит с дополнительными уточнениями и спецификациями, но это важный бит здесь.Поскольку это функция-член, ее можно вызывать для rvalues, как и Special :: get_lvalue, как если бы вы написали A().operator=(a)
вместо A() = a
.
int() = 1
явно запрещено какВы обнаружили, потому что у int нет оператора = реализованного таким же образом.Тем не менее, это небольшое несоответствие между типами на практике не имеет значения (по крайней мере, не так, как я обнаружил).
POD означает простые старые данные и представляет собой набор требований, которые указывают, что использование memcpy эквивалентнок копированию.Non-POD - это любой тип, для которого вы не можете использовать memcpy для копирования (естественная противоположность POD, здесь ничего не скрыто), что обычно является типом, который вы пишете на C ++.Будучи POD или не POD не меняет ничего из вышеперечисленного, и это действительно отдельная проблема.