views:

218

answers:

3

Hello. I'm quite new to smart pointers and was trying to refactor some existing code to use auto_ptr. The question I have is about double pointers and their auto_ptr equivalent, if that makes sense.

I have a function that accepts a double pointer as its parameter and the function allocates resources for it:

void foo ( Image** img ) { ... *img = new Image(); ...}

This function is then used like this:

Image* img = NULL;
foo ( &img );
...
delete img;


I want to use auto_ptr to avoid having to call delete explicitly. Is the following correct?

void foo ( auto_ptr<Image>* img ) { ... *img = auto_ptr<Image>(new Image()); ...}

and then

auto_ptr<Image> img = NULL;
foo ( &img );

Thanks.

+7  A: 

std::auto_ptr<> has weird copy semantics (actually it's move semantics, rather than copy semantics) and is often not what you want when you want a smart pointer. For example, it cannot be put into STL containers.
If your standard library comes with TR1 support, use std::tr1::shared_ptr<> instead. (If it doesn't, use boost's boost::shared_ptr<>, which is what std::tr1::shared_ptr<> was taken from.)

If you want to stick with std::auto_ptr<> for your code, you can pass it into the function per non-const reference:

void foo ( std::auto_ptr<Image>& img ) { ... img.reset(new Image();) ...}

std::auto_ptr<Image> img;
foo ( img );
...
// no need to delete

Or you could just return the pointer:

std::auto_ptr<Image> foo () {return std::auto_ptr<Image> img(new Image();)}
sbi
OK, thanks. Got your answer faster than I could edit, heh.
Pin
A: 

It depends on whether or not your STL's implementaton of auto_ptr overrides the '&' operator to return a pointer-to-pointer (most smart pointer classes tend to, but not all auto_ptr implementations do).

If you really want to re-write your code to pass auto_ptr objects around, then you should do something more like this instead, which would be safer:

void foo ( std::auto_ptr<Image> &img ) { ... img.reset(new Image()); ...}

std::auto_ptr<Image> img;
foo ( img );
Remy Lebeau - TeamB
sbi
A: 

Since you are refactoring, I would go one step further and convert the parameter into a return value:

// void foo( Image ** img )
std::auto_ptr<Image> foo() {
   std::auto_ptr<Image> tmp( new Image() );
   // ...
   return tmp;
}

Even if I prefer removing the requirement from the interface (so that the caller can decide to change the code to use any other type of smart pointer at will):

Image* foo() {
   std::auto_ptr<Image> tmp( new Image() );
   // ...
   return tmp.release();
}
int main() {
   std::auto_ptr<Image> ptr( foo() );
}
David Rodríguez - dribeas