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