Когда бы вы использовали std :: auto_ptr вместо boost :: shared_ptr? - PullRequest
17 голосов
/ 04 августа 2009

Мы в значительной степени перешли на использование boost::shared_ptr во всем нашем коде, однако у нас все еще есть отдельные случаи, когда мы используем std::auto_ptr, включая одноэлементные классы:

template < typename TYPE >
class SharedSingleton
{
public: 
    static TYPE& Instance()
    {
        if (_ptrInstance.get() == NULL)
            _ptrInstance.reset(new TYPE);
        return *_ptrInstance;
    }

protected: 
    SharedSingleton() {};

private:
    static std::auto_ptr < TYPE > _ptrInstance;
};

Мне сказали, что есть очень веская причина, почему это не было сделано shared_ptr, но я не понимаю, почему? Я знаю, что auto_ptr будет в конечном итоге помечено как устаревшее в следующем стандарте, поэтому я бы хотел знать, что / как я могу заменить этой реализацией .

Кроме того, есть ли другие причины, по которым вы бы рассмотрели возможность использования auto_ptr вместо shared_ptr? И вы видите какие-либо проблемы с переходом на shared_ptr в будущем?


Редактировать:

  1. Так что в ответ на вопрос «могу ли я смело заменить auto_ptr на shared_ptr в приведенном выше коде», ответ - да, однако я получу небольшой удар по производительности.
  2. Когда auto_ptr в конечном итоге помечается как устаревший, и мы переходим к std::shared_ptr, нам необходимо тщательно протестировать наш код, чтобы убедиться, что мы придерживаемся другой семантики владения.

Ответы [ 3 ]

35 голосов
/ 04 августа 2009

auto_ptr и shared_ptr решают совершенно разные задачи. Одно не заменяет другое.

auto_ptr - это тонкая оболочка вокруг указателей для реализации семантики RAII , так что ресурсы всегда высвобождаются даже при возникновении исключений. auto_ptr не выполняет никакого подсчета ссылок и т. П., Не заставляет несколько указателей указывать на один и тот же объект при создании копий. На самом деле, это очень разные. auto_ptr - один из немногих классов, где оператор присваивания изменяет объект source . Рассмотрим этот бесстыдный плагин со страницы auto_ptr википедии :

int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;

y = x;

cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i

Обратите внимание, как выполняется

y = x;

изменяет не только у, но и х.

Шаблон boost::shared_ptr позволяет легко обрабатывать несколько указателей на один и тот же объект, и объект удаляется только после того, как последняя ссылка на него вышла из области видимости. Эта функция бесполезна в вашем сценарии, который (пытается) реализовать Singleton . В вашем сценарии всегда есть 0 ссылок на 1 ссылку на единственный объект класса, если таковой имеется.

В сущности, auto_ptr объекты и shared_ptr объекты имеют совершенно разную семантику (поэтому вы не можете использовать первое в контейнерах, но делать это с последним хорошо), и я уверен, что у вас есть хорошие тесты для отлова любые регрессии, которые вы ввели при переносе кода. : -}

14 голосов
/ 04 августа 2009

Другие ответили, почему этот код использует auto_ptr вместо shared_ptr. Чтобы ответить на другие ваши вопросы:

Чем / как я могу заменить эту реализацию?

Используйте либо boost::scoped_ptr, либо unique_ptr (доступно как в Boost, так и в новом стандарте C ++). И scoped_ptr, и unique_ptr обеспечивают строгое владение (и не требуют подсчета ссылок), и они избегают удивительной семантики удаления-при-копировании auto_ptr.

Кроме того, есть ли другие причины, по которым вы решили бы использовать auto_ptr вместо shared_ptr? И вы видите какие-либо проблемы с переходом на shared_ptr в будущем?

Лично я бы не стал использовать auto_ptr. Удалить при копировании слишком не интуитивно понятно. Херб Саттер, похоже, согласен . Переключение на scoped_ptr, unique_ptr или shared_ptr не должно вызвать проблем. В частности, shared_ptr должна быть заменой, если вас не волнует подсчет ссылок. scoped_ptr является заменой, если вы не используете auto_ptr возможности передачи права собственности. Если вы используете передачу права собственности, то unique_ptr - это почти полная замена, за исключением того, что вам вместо этого нужно явно вызвать move для передачи права собственности. См. здесь для примера.

1 голос
/ 04 августа 2009

auto_ptr - единственный вид интеллектуального указателя, который я использую. Я использую его, потому что я не использую Boost, и потому что я обычно предпочитаю, чтобы мои бизнес / прикладные классы явно определить семантику и порядок удаления, а не зависеть от коллекции или отдельные умные указатели.

...