tags:

views:

337

answers:

3

I am not quite clear if auto_ptr will help me in this case:

class A
{
  A(const B& member)
   : _member(B)
  {};

...
  const B& _member;
};


A generateA() {
   auto_ptr<B> smart(new B());
   A myA(*smart);
   return myA;
}

Will the myA._member reference be valid when smart leaves its enclosing scope? If auto_ptr isn't the answer here, what is?

EDIT: I see where I confused everyone; I have to return myA outside the scope, which is why I care about _member being valid after smart exits the scope.

+6  A: 

It won't help you. _member will become a dangling handle. This is because auto_ptr guarantees destruction at end of scope: no more, and no less.

There are 2 possible answers.

  • You can make _member's type boost::shared_ptr<const B>.
  • Alternatively, if class B is small, copyable, monomorphic, and object identity doesn't need to be preserved, you can make _member a value, and store a copy of the argument there. This is by far the simplest option but obviously it is quite limiting.

In response to your edit: That is indeed the case that I was talking about. By returning myA by value, a copy is created, and the copy's _member refers to the already destructed local. As described, both shared_ptr and value semantics solve this.

no need to make the original type shared_ptr too. shared_ptr has a constructor which takes a std::auto_ptr and takes ownership from it.
Evan Teran
Cool, didn't know that :) Still, I'd make both into shared_ptrs for clarity.
(removed the note from my post)
Note that in the example given, there will not be a dangling handle as both the smart pointer and the class it's copied into have the same scope. But it's a poor example and you probably captured the spirit of the question if not the letter.
Dan Olson
Yep, I didn't even notice myA was a local, but I'm pretty sure he didn't mean it that way.
OK, now you guys confused me; I did mean myA as a local (my hands are tied there). If I switch _member to a shared_ptr<B> (which makes sense to me), when myA leaves the scope, will _member still be valid?
Max Maximus
Well, at the point at which myA "leaves the scope" (is destructed), _member will still be valid whether you use a shared_ptr or not (Martin explained why). [...]
[...] However, if you then return myA by value, or pass it to someone who stores it, and later you use it, the member ref in that _copy_ will be dangling. And _that_ is the case shared_ptr protects you from.
(edited to respond to your latest edit)
+2  A: 

The auto_ptr class is a wrapper over normal pointers. They take care of de-allocation when the stack is unwound (the destructor of auto_ptr gets called which in turn frees your contained object).

Note well, that your A object is also created on the stack. When the scope ends, both A and the auto_ptr will be deallocated. Beyond this point trying to access the A object will give you a compile-time error.

Assuming the A object was created somewhere outside the block, then you have a real problem. Since, the A object stores a reference to the B object, outside the block-scope, this reference becomes invalid.

Note also that with C++0x, auto_ptr has been deprecated. Use a unique_ptr instead. Do take a look at the General Purpose Smart Pointers that are coming your way in C++0x.

dirkgently
A: 
{
   auto_ptr<B> smart(new B());
   A myA(*smart);
}

Both the pointer held in 'smart' and the object 'myA' will be destroyed at the end of this scope. But that should be what you want with this snipit of code.

Once the scope ends 'myA' will be destroyed first (its declared last).
Then following this smart will be destroyed and its destructor will delete the pointer.

Since there is no way to reference 'smart' or 'myA' I would hope that you want the poiner deleted at this point.

Alternatively you could do this:

{
    B  myB;
    A  myA(myB);
}
Martin York