Выделение временного unique_ptr

unique_ptr<A> myFun()
{
    unique_ptr<A> pa(new A());
    return pa;
}

const A& rA = *myFun();

Этот код компилируется, но rA содержит мусор. Может кто-нибудь объяснить мне, почему этот код недействителен?

Примечание: если я назначу возврат myFun к именованной переменной unique_ptr перед разыменованием ее, она отлично работает.

Ответ 1

unique_ptr передаст право собственности другому unique_ptr, но в вашем коде нет ничего, чтобы захватить собственность с возвращаемого указателя. Другими словами, он не может передать право собственности, поэтому он будет разрушен. Правильный способ:

unique_ptr<A> rA = myFun(); // Pass the ownership

или

const A rA = *myFun(); // Store the values before destruction

В вашем коде возвращаемый указатель будет скомпенсирован, и ссылка ссылается на объект, который быстро разрушается, после чего с использованием этой ссылки вызывается поведение undefined.

Ответ 2

unique_ptr<A> myFun()
{
    unique_ptr<A> pa(new A());
    return pa;
}

const A& rA = *myFun();

Что вы сделали в этой последней строке:

unique_ptr<A>* temporary = new unique_ptr<A>(nullptr);
myFun(&temporary);
const A& rA = *temporary.get();
delete temporary; // and free *temporary

Когда вы удаляете temporary, у вас есть контракт с вами, что он владеет указателем и памятью, на которую ссылается. Таким образом, он разрушает A и освобождает память.

Между тем, вы скрытно указали на эту память как ссылку на объект по этому адресу.

Вы можете либо перенести указатель на локальный уникальный_ptr:

unique_ptr<A> a = myFun();

или вы можете скопировать объекты:

A = *myFun().get();

"A", к которому myFun() временный разрушается только в конце инструкции, поэтому он присутствует для копии.