0

Take a look at this code:

Foo &Bar::Copy()
{
    return Bar();
}

The class Bar is inherited from Foo, and Foo is an abstract class. But when I call Bar() and return it, is it safe to do so? Or would I be returning the address of a local variable that would be freed by the end of the Copy() function?

Advice is greatly appreciated!

AutoBotAM
  • 1,485
  • 3
  • 18
  • 24
  • possible duplicate of [C++ Returning reference to local variable](http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable) – GWW Nov 15 '11 at 16:14
  • @GWW - No it isn't. I didn't know if returning a constructor counted as returning a local allocation or not. It will probably be beneficial to anyone else confused about the same thing. – AutoBotAM Nov 15 '11 at 16:32
  • Actually this shouldn't even compile because an rvalue is bound to a non-const reference. – celtschk Nov 15 '11 at 17:02

3 Answers3

1

When calling Bar(); you call constructor on an implicit temporary object to which reference is returned. If you intend to create a Clone() like function a typical solution is to create the clone on the heap with new. You may use a kind of smart pointer to simplify life cycle management. You may also apply covariant return type to avoid type conversions in some cases using signature: Bar &Bar::Copy()

jszpilewski
  • 1,632
  • 1
  • 21
  • 19
1

You're not returning a ctor. Bar(); invokes the ctor, creating a temporary object. You're then returning a reference to that temporary object.

Since a ctor in C++ doesn't have a name, you can't do many of the usual things you could on normal functions, such as getting/returning a pointer to a function. It's no entirely clear what you're really trying to accomplish here, but if you want to return something that will construct an object, you usually need to define a static member function that invokes the ctor, and return a pointer to that static member function.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Well in the long run I'm trying to create an array of `Foo*` pointers (in theory, its not called Foo in my real program). I was worried that the lifetimes of the pointers being inserted into it would make it prone to undefined behavior, so I was trying to insert copies so the lifetimes of the addresses would cohere with the array. I suppose using a smart pointer and allocating on the heap would be best for this though, as jszpilewski has mentioned. – AutoBotAM Nov 15 '11 at 17:45
  • @AutoBotAM: You might also want to look at Boost [ptr_vector](http://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_vector.html). – Jerry Coffin Nov 15 '11 at 17:52
  • The pointer container library over all looks like what I need. Will try. – AutoBotAM Nov 15 '11 at 18:01
0

This is an undefined behaviour, because temporary Bar object will be destroyed at ;.

Foo Bar::Copy()
{
    return Bar();
}

is safer. BUT thanks to @Cat Plus Plus and @celtschk, I realized that this method leads to slicing, losing the all Bar specific information. In order to keep the Bar object Copy() must return either a reference or a pointer to the object. Here we are at the beginning again as this is UB. So Barmust be allocated dynamically instead, that its reference/pointer lives at the out of Copy() function. Who should be responsible for deleting this dynamically generated Bar object?

#include <memory>
std::shared_ptr<Foo> Bar::Copy()
{
    return std::shared_ptr(new Bar());
}

shared_ptr will do this automatically for you.

ali_bahoo
  • 4,732
  • 6
  • 41
  • 63