C++ FAQ question [26.13] What should be returned from a function?

K

krel

Two of the cases mentioned are:

- shared_ptr to a member that was allocated via new — this has tradeoffs
that are very similar to those of returning a member by pointer or by
reference; see those bullets for the tradeoffs. The advantage is that
callers can legitimately hold onto and use the returned pointer after
the this-object dies.

- local auto_ptr or shared_ptr to freestore-allocated copy of the datum.
This is useful for polymorphic objects, since it lets you have the
effect of return-by-value yet without the "slicing" problem. The
performance needs to be evaluated on a case-by-case basis.

Perhaps it's the wording, but I don't understand the difference between
these two, supposedly different, options.
 
R

Robert Fendt

- shared_ptr to a member that was allocated via new — this has tradeoffs
that are very similar to those of returning a member by pointer or by
reference; see those bullets for the tradeoffs. The advantage is that
callers can legitimately hold onto and use the returned pointer after
the this-object dies.

struct Foo
{
foo() : str_(new std::string("Hello, World")) {}

shared_ptr<std::string> get_str() {return str_;}

shared_ptr<std::string> str_;
};

get_str() returns a shared_ptr to a string, and since inside the
Foo class this member is also held via a shared_ptr (the FAQ
should perhaps be a bit more clear on that point), it is legal
to get a pointer, i.e.

Foo f;
shared_ptr<std::string> my_str = f.get_str();

and hold on to it even after the Foo object is deleted. If it
would be a reference or a naked pointer, then doing something
like that would lead to big trouble.
- local auto_ptr or shared_ptr to freestore-allocated copy of the datum.
This is useful for polymorphic objects, since it lets you have the
effect of return-by-value yet without the "slicing" problem. The
performance needs to be evaluated on a case-by-case basis.

class Bar;

class Foo
{
public:
virtual void do_something() {};

Foo() {};
virtual ~Foo() {};

static Foo* get_instance() {return new Bar;}
};

class Bar: public Foo
{
public:
void do_something() {x = 0;}

private:
int x;
}

In this scenario, one e.g. gets an instance via a factory without
knowing exactly what implementation of the base class one gets
(and without caring about it). If the factory would try to
return the object by value, then this does not work, since

Foo my_copy = Foo::get_instance();

would slice the temporary Bar object down to a Foo object.
However, if you return a pointer, you get polymorphism, and the
following works just fine:

std::auto_ptr<Foo> my_ptr(Foo::get_instance());

By doing this, the returned value is destroyed when exiting the
current scope, just like a returned value copy on the stack
would, since you 'wrap' the heap object in a stack object
taking care of memory management. On the other hand, you still
get full polymorphism (i.e., you don't have to know that the Foo
object returned is actually a Bar object).
Perhaps it's the wording, but I don't understand the difference between
these two, supposedly different, options.

HTH.

Regards,
Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top