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

Discussion in 'C++' started by Neal Coombes, Sep 15, 2005.

  1. Neal Coombes

    Neal Coombes Guest

    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 <>
    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! ]
     
    Neal Coombes, Sep 15, 2005
    #1
    1. Advertising

  2. Neal Coombes

    Guest

    * 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.
     
    , Sep 15, 2005
    #2
    1. Advertising

  3. Neal Coombes

    Chris Newton Guest

    Neal Coombes wrote:
    > 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
     
    Chris Newton, Sep 16, 2005
    #3
  4. In article <>,
    writes
    >* 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.
    --
    Francis Glassborow ACCU
    Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
    For project ideas and contributions: http://www.spellen.org/youcandoit/projects
     
    Francis Glassborow, Sep 16, 2005
    #4
  5. Neal Coombes

    Neal Coombes Guest

    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
     
    Neal Coombes, Sep 19, 2005
    #5
  6. Neal Coombes

    Guest

    That's why I said "usually".
     
    , Sep 22, 2005
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark Odell

    Using size_t clearly (appropriately?)

    Mark Odell, Jun 28, 2006, in forum: C Programming
    Replies:
    40
    Views:
    1,125
    Stephen Sprunk
    Jul 13, 2006
  2. Replies:
    1
    Views:
    2,739
    Adrienne Boswell
    Sep 24, 2008
  3. A
    Replies:
    7
    Views:
    644
  4. Ferrous Cranus
    Replies:
    40
    Views:
    440
    Ferrous Cranus
    Feb 22, 2013
  5. Nick the Gr33k
    Replies:
    1
    Views:
    110
    Nick the Gr33k
    Nov 2, 2013
Loading...

Share This Page