Подтвердить что ты не робот

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

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

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

Ответ 1

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

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

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 имеют совершенно другую семантику (почему вы не можете использовать первое в контейнерах, но делать это с последним в порядке), и я уверен, что у вас есть хорошие тесты, чтобы поймать любые регрессии, которые вы вводили при портировании кода.: -}

Ответ 2

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

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

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

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

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

Ответ 3

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