Возврат std::unique_ptr
из фабричного метода - это нормально и должно быть рекомендуемой практикой.Сообщение, которое оно передает (IMO): Теперь вы являетесь единственным владельцем этого объекта.Кроме того, для вашего удобства объект знает, как уничтожить себя.
Я думаю, что это гораздо лучше, чем возвращать необработанный указатель (где клиент должен помнить, как и если избавляться отэтот указатель).
Однако я не понимаю ваш комментарий об освобождении указателя для продления срока его службы.В общем, я редко вижу какую-либо причину для вызова release
на smartpointer, так как я думаю, что указатели всегда должны управляться какой-то структурой RAII (почти единственная ситуация, когда я вызываю release
, это помещать указатель в другуюуправление структурой данных, например unique_ptr
с другим удалителем, после того, как я сделал что-то для дополнительной очистки).
Следовательно, клиент может (и должен) просто хранить unique_ptr
где-то (например, другой unique_ptr
, который был сконструирован из возвращенного), пока ему нужен объект (или shared_ptr
, если им нужно несколько копий указателя).Таким образом, клиентский код должен выглядеть примерно так:
std::unique_ptr<FooBar> myFoo = Foobar::factory(data);
//or:
std::shared_ptr<FooBar> myFoo = Foobar::factory(data);
Лично я бы также добавил typedef
для возвращаемого типа указателя (в данном случае std::unique_ptr<Foobar>
) и / или используемого средства удаления (в этом случаеstd :: default_deleter) к вашему заводскому объекту.Это облегчает задачу, если впоследствии вы решите изменить распределение вашего указателя (и, следовательно, вам понадобится другой метод уничтожения указателя, который будет отображаться как второй параметр шаблона std::unique_ptr
).Поэтому я бы сделал что-то вроде этого:
class Foobar {
public:
typedef std::default_deleter<Foobar> deleter;
typedef std::unique_ptr<Foobar, deleter> unique_ptr;
static unique_ptr factory(DataObject data);
}
Foobar::unique_ptr myFoo = Foobar::factory(data);
//or:
std::shared_ptr<Foobar> myFoo = Foobar::factory(data);