This can happen more easily than you may think if a function throws an exception.
Below is an example of using them. Be warned that the MS VC library and the gcc library seem to handle auto_ptr a bit differently. The MS STL library simply transfers ownership of the pointer (so you can use it after assigning it) whilst the gcc STL library actually sets the original pointer to NULL (thus, you can't use it after assigning it). We should be very careful about assigning auto pointers because of this.
Also, I note from the STL code that the destructor deletes the pointer, it doesn't allow for an array. What I mean is that if you do this:
int * i = new int [100];
You are supposed to delete it like this:
delete [] i;
Since the auto_ptr doesn't know to do that, this will not work properly:
auto_ptr
However I should point out that if you are using STL in the first place, you should probably be using a vector instead of an array of ints in the first place. ;)
Note also you don't delete an auto_ptr - you simply let it delete itself in the destructor when it goes out of scope.
#include
#include
#include
#include
using namespace std;
class Widget
{
public:
Widget () { cout << "widget constructor" << endl; };
~Widget () { cout << "widget destructor" << endl; };
void test () { cout << "widget test" << endl; }
};
// output operator for auto_ptr (see Josuttis p 47)
template
ostream& operator<< (ostream& strm, const auto_ptr
{
if (p.get () == NULL)
strm << "NULL";
else
strm << p.get ();
return strm;
} // end of ostream& operator<<
void sub (void)
{
auto_ptr
auto_ptr
w->test (); // test it (use like a normal pointer)
cout << "Before assignment..." << endl;
cout << " w: " << w << endl;
cout << " x: " << x << endl;
// transfer ownership of pointer from w to x
x = w;
x->test (); // test it again
cout << "After assignment..." << endl;
cout << " w: " << w << endl;
cout << " x: " << x << endl;
throw runtime_error ("Trouble brewing");
}
int main (void)
{
try
{
cout << "Before sub" << endl;
sub ();
cout << "After sub" << endl;
}
catch (runtime_error & e)
{
cout << "Exception: " << e.what () << endl;
}
return 0;
} // end of main
Output on Linux
Before sub
widget constructor
widget test
Before assignment...
w: 0x804a880
x: NULL
widget test
After assignment...
w: NULL
x: 0x804a880
widget destructor
Exception: Trouble brewing
Output on MS VC++
Before sub
widget constructor
widget test
Before assignment...
w: 00300030
x: NULL
widget test
After assignment...
w: 00300030
x: 00300030
widget destructor
Exception: Trouble brewing
Notice the difference, after the assignment the pointer still exists (is not NULL) in this case.