Я думал, что возвращение make_unique - это r-значение ...
Это так. Но для типов классов, таких как std::unique_ptr<...>
, присваивание является вызовом перегруженной функции-члена. Вы можете передавать значения в качестве аргументов в функции. А точнее, вызовите функции-члены для rvalues.
Например, когда вы изучаете std::bitset
, вы видите, что его тип reference
на самом деле является типом класса. Оператор присваивания для этого типа перегружен. Он принимает bool
, но фактически выполняет побитовую операцию для манипулирования флагом в упакованной памяти bitset
.
Он работает для unique_ptr
значений r, поскольку он перегружен (и неявно генерируется для других типов классов) без каких-либо ref-квалификаторов. * 1017 Т.е. *
unique_ptr& operator=( unique_ptr&& r ) noexcept;
... а не ...
unique_ptr& operator=( unique_ptr&& r ) & noexcept;
// Can only be used on lvalues, no overload for rvalues
Что было бы для очень маленькой выгоды. И маловероятно, что неявно сгенерированный будет когда-либо только для lvalues. Большая часть кода (часть которого предшествует C ++ 11) использует присваивание для значений r без переопределения операторов. Так что это сломало бы существующие кодовые базы.