Безопасное использование std::tr1::shared_ptr
Этот подход небезопасен?
#include <tr1/memory>
Foo * createFoo()
{
return new Foo(5);
}
int main()
{
std::tr1::shared_ptr<Foo> bar(create());
return 0;
}
Или это было бы предпочтительнее для createFoo
вернуть shared_ptr<Foo>
объект?
2 ответа
Пример безопасен: если shared_ptr
конструктор выдает исключение, это delete
Аргумент указателя перед броском (черновик стандарта, 20.9.11.2.1).
Будь то create
должен вернуть shared_ptr
зависит от того, что его клиенты могут разумно хотеть сделать с его результатом. Если все, что они когда-либо делают, это завернуть его в shared_ptr
, затем верните это для дополнительной безопасности. (Да, shared_ptr
может ввести некоторую связь.)
Ваш пример безопасен так, как вы его написали. Тем не менее, вы можете сделать его еще более герметичным, если ваш заводской метод createFoo()
вернуть автоматический указатель вместо необработанного указателя. Таким образом, вы гарантированно, что не будет никаких утечек.
Итак, что вы получите:
#include <memory>
#include <tr1/memory>
std::auto_ptr<Foo> createFoo()
{
return std::auto_ptr<Foo>(new Foo(5));
}
int main()
{
std::tr1::shared_ptr<Foo> bar(createFoo());
return 0;
}
Конечно, также возможно, чтобы ваш фабричный метод возвратил shared_ptr, но это может быть расценено как излишнее, поскольку возвращаемый указатель, как правило, выходит за рамки довольно быстро, так как он будет использоваться в присваивании или конструкторе. Кроме того, использование auto_ptr более четко указывает намеченное использование указателя, что всегда является плюсом, когда люди, незнакомые с вашим кодом, должны его понимать.