Здесь нет утечки. В общем случае объект, принадлежащий std::unique_ptr
, никогда не просочился, если .release()
не вызывается для владельца std::unique_ptr
.
Однако ваша программа имеет неопределенное поведение, поскольку время жизни не правильное. Если вы храните ссылку или указатель на принадлежащий объект, вы берете на себя некоторую ответственность за обеспечение правильного времени жизни объекта.
give_a_number()
возвращает по значению std::unique_ptr
, владеющий объектом int
. Поэтому std::unique_ptr
материализуется как временный объект в операторе
int& ret = *give_a_number();
Вы не перемещаете этот временный объект ни в один постоянный экземпляр std::unique_ptr
. Поэтому, когда временный объект уничтожается в конце оператора, int
, которым он владеет, также уничтожается. Теперь ваша ссылка свисает.
Затем вы используете висячую ссылку в return ret;
, вызывая неопределенное поведение.
Вы можете сохранить ссылку на принадлежащий объект, но если вы это сделаете, вы должен гарантировать, что экземпляр std::unique_ptr
, владеющий ссылкой, устареет ссылка int
, чтобы избежать проблем с жизненным циклом. Например, все в порядке:
int main(){
return *give_a_number(); // `std::unique_ptr` temporary outlives return value initialization
}
int main(){
auto ptr = give_a_number(); // `ptr` lives until `main` returns
int& ret = *ptr;
return ret;
}
Обычно безопаснее просто сохранить смарт-указатель в автоматической переменной c, как указано выше, и получить объект путем разыменования с помощью *ptr
, где это необходимо. , std::unique_ptr
и принадлежащий ему объект затем живут до конца блока, если он не перемещен из.
Но совершенно правильно, например, передать *ptr
в функцию по ссылке. Поскольку ptr
переживает такой вызов функции, проблем не будет.
Это также работает, если вы передаете *give_a_number()
непосредственно в качестве аргумента функции, потому что временный std::unique_ptr
также переживет такой вызов. Но в этом случае std::unique_ptr
и принадлежащий ему объект будут жить только до конца оператора (полного выражения), а не до конца блока.