Безопасное использование 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 более четко указывает намеченное использование указателя, что всегда является плюсом, когда люди, незнакомые с вашим кодом, должны его понимать.

Другие вопросы по тегам