Когда бы вы использовали std :: auto_ptr вместо boost :: shared_ptr?

StackOverflow https://stackoverflow.com/questions/1227379

Вопрос

Мы в значительной степени перешли на использование 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 в будущем?

<Ч>

Изменить.

<Ол>
  • Таким образом, в ответ на вопрос "могу ли я смело заменить auto_ptr на shared_ptr в приведенном выше коде "", ответ будет положительным - однако я получу небольшой удар по производительности .
  • Когда auto_ptr в конечном итоге помечается как устаревший, и мы переходим к std :: shared_ptr , нам необходимо тщательно протестировать наш код, чтобы убедиться в его соблюдении. различной семантикой владения.
  • Это было полезно?

    Решение

    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;
    

    изменяет не только y, но и x.

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

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

    Другие советы

    Другие ответили, почему этот код использует 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 для передачи права собственности. См. здесь для примера.

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top