Return appropriately by value, (smart) pointer, or reference

N

Neal Coombes

Posted to comp.lang.c++.moderated with little response. Hoping for
better from the unmoderated groups:

-------- Original Message --------
Subject: Return appropriately by value, (smart) pointer, or reference
Date: 27 Aug 2005 15:13:23 -0400
From: Neal Coombes <[email protected]>
Organization: Aioe.org NNTP Server
To: (Usenet)
Newsgroups: comp.lang.c++.moderated

I think I already know how to write such a coding standard item, but I'm
very interested in finding out the right answer. :)

In Herb and Andrei's Coding Standards book Item 25 is about taking
parameters appropriately by value, (smart) pointer, or reference. There
is however no item about how to return.

So If anyone is up for it, I'd be very interested in how to write Item
25b. Return appropriately by value, (smart) pointer, or reference.

Thanks,

Neal

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

kevin.hall

* Don't return references or pointers to function-local data. They
will be destroyed by the time the calling function can access them

* Return a smart pointer if you need to return a new'd object that may
not be checked for by the calling function. Ex

MyObject* MyFancyFunction(std::string& s)
{
// ...
return new MyObject(<some data>);
}

// in calling function:
MyFancyFunction(); // oops! The allocated MyObject is now
lost forever

Instead do:

std::auto_ptr<MyObject> MyFancyFunction(std::string& s)
{
// ...
return std::auto_ptr<MyObject>(new MyObject(<some data>));
}

// in calling function:
MyFancyFunction(); // phew! auto_ptr will now delete the
object for me if I don't need it

* Returning by reference usually doesn't make a lot of sense. In
non-class functions, you don't want to return a reference to a local
variable. In non-class functions, references can be passed in --
usually you don't have to return that reference, just modify the value
of the variable being referenced. In class-functions, it's considered
good practice to use get/set methods instead of returning a reference
to a private member. That way, if you need to abstract the private
member, you can do so more easily.

* When pointers and references don't make sense, return by value.
 
C

Chris Newton

Neal said:
In Herb and Andrei's Coding Standards book Item 25 is about taking
parameters appropriately by value, (smart) pointer, or reference.
There is however no item about how to return.

So If anyone is up for it, I'd be very interested in how to write
Item 25b. Return appropriately by value, (smart) pointer, or
reference.

I'll try to answer the question you've asked in a moment, but I think
the issue is deeper than this.

There are several other ways to get data out of a function. At the very
least, you have to consider exceptions, "out" parameters, and shared
data areas like the state of an object. On top of those, there are more
devious variations on the theme, such as passing in a function object or
using call-backs.

In addition, return values in C++ can provide only a single piece of
information. To return more, we must either use a compound type like a
struct or tuple object, or we must use other mechanisms to supplement or
replace the return value.

In other words, return values do not operate in a vacuum. The best use
for them can depend intimiately on what other approaches are
(potentially) being used as well.

With that caveat out of the way, here are a few guidelines that come to
mind immediately.


1. By default, return by value. This provides natural semantics, and
minimal scope for misunderstand or misuse.

1a. Help your optimiser to make this as efficient as possible. IIRC,
Scott Meyers wrote on this subject in one of his Effective books.

1b. Choose another technique with polymorphic types, to avoid slicing.

1c. Emphasise readability at the point where your function is called.

1ci. If your function's primary purpose is to return some data, name it
after that data.

1cii. Avoid "out" parameters where a return value could be used instead.

It's cumbersome to write this:
SomeType data;
GetDataInto(data);
DoSomethingWith(data);
when you could write this:
DoSomethingWith(Data());

1d. If a returned value is likely to be an intermediate step in a
computation, consider returning placeholder objects and using expression
template techniques to improve effiency.



2. Return a reference where a specific item of internal data should be
directly accessible, as with [] operators for data structures. Also
return a reference from operators that can be chained, such as
assignment operators and insertion/extraction for I/O streams.

2a. Provide versions for const, non-const or both, as appropriate.

2b. Be clear about what conditions invalidate the reference.


3. If you're returning any pointer type, smart or otherwise, be clear
whether a NULL value is possible, and what its significance is if so.


4. Raw pointers are ambiguous about intent, and are best avoided.


5. Where you want to return a pointer to a dynamically allocated object,
or an object of a polymorphic type, use a suitable smart pointer type to
ensure that ownership is transferred or shared as appropriate while
preserving the polymorphic behaviour. At least use an auto_ptr to make
sure ignoring a return value can't create an inadvertent memory leak.
Specify the ownership policy in a comment if it isn't clear from the code.


6. Where you're identifying a particular location in a data structure,
an iterator or some sort of key value may be a more powerful way to
return the information. If a pointer would provide uncontrolled access
to (part of) an array, returning a proxy object to represent that array
slice can provide range-checking for safety, while still offering almost
direct access to the underlying data structure for performance.


I'm sure these could be rearranged into something rather better written
and I'm sure there are omissions, but that's the starting point my
stream of consciousness came up with.

Hope that helps,
Chris
 
F

Francis Glassborow

* Don't return references or pointers to function-local data. They
will be destroyed by the time the calling function can access them

* Return a smart pointer if you need to return a new'd object that may
not be checked for by the calling function. Ex

MyObject* MyFancyFunction(std::string& s)
{
// ...
return new MyObject(<some data>);
}

// in calling function:
MyFancyFunction(); // oops! The allocated MyObject is now
lost forever

Instead do:

std::auto_ptr<MyObject> MyFancyFunction(std::string& s)
{
// ...
return std::auto_ptr<MyObject>(new MyObject(<some data>));
}

// in calling function:
MyFancyFunction(); // phew! auto_ptr will now delete the
object for me if I don't need it

* Returning by reference usually doesn't make a lot of sense. In
non-class functions, you don't want to return a reference to a local
variable. In non-class functions, references can be passed in --
usually you don't have to return that reference, just modify the value
of the variable being referenced. In class-functions, it's considered
good practice to use get/set methods instead of returning a reference
to a private member. That way, if you need to abstract the private
member, you can do so more easily.

* When pointers and references don't make sense, return by value.
Returning references to static and member data by const reference makes
a great deal of sense when the data is relatively large. Returning an
item by reference that has been passed in as a reference parameter is
also sensible if you want to use the function as part of a larger
expression.
 
N

Neal Coombes

Thanks for the Help guys. I'll go off and try to write such an item for
my companies coding standard, and post it here (in a new thread) for
more feedback.

Neal
 

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,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top