Может ли кто-нибудь объяснить просто причину, почему это не работает:
std::shared_pointer<Bar> getSharedPointer() {
return std::make_shared<Bar>();
}
...
auto foo = getSharedPointer().get();
Видимо, с помощью необработанного указателя foo
вызовет segfault, потому что время жизни общего указателя, возвращенного getSharedPointer()
закончится. Каким-то образом я ожидал бы, что он продлится до конца своей области (как и любой блок внутри него).
Правильно ли это и есть ли аналогичные примеры этой ситуации?
За getSharedPointer().get();
, getSharedPointer()
возвращает временный std::shared_ptr
которая будет немедленно уничтожена после выражения, и управляемый им указатель также будет удален. После этого foo
повиснет, любое разыменование на нем вызывает UB.
auto foo = getSharedPointer().get();
// foo have become dangled from here
Вместо этого вы можете использовать именованную переменную:
auto spb = getSharedPointer();
auto foo = spb.get();
// It's fine to use foo now, but still need to note its lifetime
// because spb will be destroyed when get out of its scope
// and the pointer being managed will be deleted too
auto foo = getSharedPointer().get();
Всякий раз, когда функция возвращает тип, который не является ссылкой, результатом вызова функции является rvalue. Кроме того, потому что функция getSharedPointer()
возвращает тип класса, результат является временным объектом.
Время жизни этого временного объекта определяется как конец вычисления самого внешнего выражения, здесь getSharedPointer().get()
, Как только foo
переменная инициализируется, владелец умного указателя уничтожается; когда последний shared_ptr
владеющий этим объектом уничтожается, объект удаляется.
Вот getSharedPointer()
всегда возвращается shared_ptr
который не разделяет управляемый объект (use_count()
1), поэтому, когда эта копия последнего shared_ptr
уничтожен, объект уничтожен и указатель на объект недействителен.
(Я не уверен, почему вы возвращаете shared_ptr
и не unique_ptr
Вот.)
Правильное использование умного указателя или любого класса, который «владеет» (управляет временем жизни) других ресурсов (ресурсов, к которым у вас все еще есть прямой доступ), заключается в поддержании «умного» указателя / владельца в течение всего времени, пока вы необходимо получить доступ к ресурсам.
Таким образом, «умный» указатель (владеющий объектом) должен быть назван. Кроме того, я не уверен, что вы действительно хотели бы скрыть тот факт, что это умный указатель с точки зрения читателя с auto
,
std::shared_pointer<Bar> foo = getSharedPointer();
// use foo.get()
Вы можете скрыть точный тип управляемого объекта:
std::shared_pointer<auto> foo = getSharedPointer();