Вы не должны действительно использовать станд.:: auto_ptr для этого. Деструктор не будет видим в точке, Вы объявляете станд.:: auto_ptr, таким образом, это нельзя было бы назвать правильно. Это предполагает, что Вы вперед объявляете свой pImpl класс и создаете экземпляр в конструкторе в другом файле.
, Если Вы используете повышение:: scoped_ptr (никакая потребность в shared_ptr здесь, Вы не будете совместно использовать pimpl ни с какими другими объектами, и это осуществляется scoped_ptr, являющимся noncopyable), Вам только нужен pimpl деструктор, видимый в точке, которую Вы вызываете scoped_ptr конструктором.
, Например,
// in MyClass.h
class Pimpl;
class MyClass
{
private:
std::auto_ptr<Pimpl> pimpl;
public:
MyClass();
};
// Body of these functions in MyClass.cpp
Здесь, компилятор генерирует деструктор MyClass. Который должен назвать деструктор auto_ptr. В точке, где auto_ptr деструктор инстанцируют, Pimpl является неполным типом. Таким образом в к auto_ptr деструктору, когда это удаляет объект Pimpl, это не будет знать, как назвать деструктор Pimpl.
повышение:: scoped_ptr (и shared_ptr) не имеют этой проблемы, потому что при вызове конструктора scoped_ptr (или метод сброса) это также делает эквивалентное указателю функции, которое это будет использовать вместо вызова, удаляют. Ключевой пункт здесь - то, что это инстанцирует функции освобождения, когда Pimpl не является неполным типом. Как примечание стороны, shared_ptr позволяет Вам определять пользовательское освобождение функция, таким образом, можно использовать для него для вещей как дескрипторы GDI или независимо от того, что можно хотеть - но это - излишество для потребностей здесь.
, Если Вы действительно хотите использовать станд.:: auto_ptr, тогда необходимо проявить дополнительную заботу путем проверки, что Вы определяете свой деструктор MyClass в MyClass.cpp, когда Pimpl полностью определяется.
// in MyClass.h
class Pimpl;
class MyClass
{
private:
std::auto_ptr<Pimpl> pimpl;
public:
MyClass();
~MyClass();
};
и
// in MyClass.cpp
#include "Pimpl.h"
MyClass::MyClass() : pimpl(new Pimpl(blah))
{
}
MyClass::~MyClass()
{
// this needs to be here, even when empty
}
компилятор генерирует код, разрушают всех членов MyClass эффективно 'в' пустом деструкторе. Таким образом в точке auto_ptr деструктор инстанцируют, Pimpl больше не является неполным, и компилятор теперь знает, как назвать деструктор.
Лично, я не думаю, что это стоит стычки проверки, что все корректно. Существует также риск, что кто-то приедет позже и уберет код путем удаления на вид избыточного деструктора. Таким образом, просто более безопасно повсюду вокруг пойти с повышением:: scoped_ptr для такого рода вещи.
Я склонен использовать auto_ptr
. Обязательно сделайте Ваш класс noncopyable (объявите частную копию ctor & оператор =, или иначе наследовались boost::noncopyable
). Если Вы используете auto_ptr
, одна морщина - то, что необходимо определить невстроенный деструктор, даже если тело пусто. (Это вызвано тем, что, если Вы позволяете компилятору генерировать деструктор по умолчанию, impl
, будет неполный тип, когда вызов к delete impl_
сгенерирован, вызвав неопределенное поведение).
существует мало для выбора между auto_ptr
& указатели повышения. Я склонен не использовать повышение на стилистических основаниях, если стандартная альтернатива библиотеки сделает.
Альтернатива повышения std::auto_ptr
boost::scoped_ptr
. Основное различие от auto_ptr
- то, что boost::scoped_ptr
noncopyable.
См. эта страница для получения дополнительной информации.
повышение:: shared_ptr особенно адаптируется для работы на pimpl идиому. Одно из основных преимуществ - то, что это позволяет не определять деструктор для класса, содержащего pimpl. Общая политика владения, возможно, оба преимущества и недостаток. Но в более позднем случае можно определить конструктора копии правильно.
Если Вы действительно педантичны нет никакой абсолютной гарантии, что использование auto_ptr
участник не требует полного определения auto_ptr
шаблонный параметр в точке, в которой это используется. Однако я никогда не видел, что это не работает.
Одно изменение должно использовать const auto_ptr
. Это работает, пока Вы можете создать свой 'pimpl' с новым выражением в списке инициализатора и гарантируете, что компилятор не может генерировать конструктора копии значения по умолчанию и методы присвоения. Невстроенный деструктор для класса включения все еще должен быть обеспечен.
При прочих равных условиях, я одобрил бы реализацию, которая пользуется просто стандартными библиотеками, поскольку это сохраняет вещи более портативными.
Не так старайтесь стрелять себе в ногу в C++, у Вас есть много возможностей:) Нет никакой реальной потребности использовать любой автоматические указатели, так как Вы отлично знаете, когда Ваш объект должен войти и из жизни (в Вашем конструкторе (конструкторах) и деструкторе).
Сохраняют его простым.