You shouldn't really use std::auto_ptr for this. The destructor wont be visible at the point you declare the std::auto_ptr, so it might not be called properly. This is assuming that you are froward declaring your pImpl class, and creating the instance inside the constructor in another file.
If you use boost::scoped_ptr (no need for shared_ptr here, you wont be sharing the pimpl with any other objects, and this is enforced by scopped_ptr being noncopyable), you only need the pinpl destructor visible at the point you call the scoped_ptr constructor.
E.g.
// in MyClass.h
class Pimpl;
class MyClass
{
private:
std::auto_ptr<Pimpl> pimpl;
public:
MyClass();
};
// Body of these functions in MyClass.cpp
Here, the compiler will generate the destructor of MyClass. Which must call auto_ptr's destructor. At the point where the auto_ptr destructor is instantiated, Pimpl is an incomplete type. So in to the auto_ptr destructor when it deletes the the Pimpl object, it wont know how to call the Pimpl destructor.
boost::scoped_ptr (and shared_ptr) don't have this problem, because when call the constructor of a scoped_ptr (or the rest method) it also makes a function-pointer-equivalent that it will use instead of calling delete. The key point here is that it instantiates the deallocation function when Pimpl is no an incomplete type. As a side note, shared_ptr allows you to specify a custom deallocation function, so you can use for it for things like GDI handles or whatever else you may want - but that's overkill for your needs here.
If you really want to use std::auto_ptr, then you need to take extra care by making sure you define your MyClass destructor in MyClass.cpp when Pimpl is fully defined.
// in MyClass.h
class Pimpl;
class MyClass
{
private:
std::auto_ptr<Pimpl> pimpl;
public:
MyClass();
~MyClass();
};
and
// in MyClass.cpp
#include "Pimpl.h"
MyClass::MyClass() : pimpl(new Pimpl(blah))
{
}
MyClass::~MyClass()
{
// this needs to be here, even when empty
}
The compiler will generate the code destruct all of the MyClass members effectively 'in' the empty destructor. So at the point the auto_ptr destructor is instantiated, Pimpl is no longer incomplete and the compiler now knows how to call the destructor.
Personally, I don't think it's worth the hassle of making sure everything is correct. There's also the risk that somebody will come along later and tidy up the code by removing the seemingly redundant destructor. So it's just safer all round to go with boost::scopped_ptr for this kind of thing.