returning a reference

Discussion in 'C++' started by Shea Martin, Oct 8, 2003.

  1. Shea Martin

    Shea Martin Guest

    Trying to avoid a temp object, and c-style funcitons
    (i.e., void doSomethingTo(Type* thisObject) ).

    <referece: code below>

    Is it safe to return a reference to an internally created object? Is
    obj's destructor called at end of main or at end of fromString()?

    This is how I uderstand it: o's copy constructor is called with obj as
    the arg, and I have avoided a temporary instance of Object.

    Is this safe?

    Thanks

    <code>
    class Object
    {
    public:
    static Object &fromString(std::string str)
    {
    Object obj;
    //process string, and set attributes of obj
    return obj;
    }
    };

    int main()
    {
    Object o = Object::fromString("attribute1,attribute2");
    cout << "att1 is " << o.getAtt1()
    << "att2 is " << o.getAtt1()
    << "att3 is " << o.getAtt1() << endl;
    }
    </code>
     
    Shea Martin, Oct 8, 2003
    #1
    1. Advertising

  2. Shea Martin

    red floyd Guest

    Shea Martin wrote:

    > Trying to avoid a temp object, and c-style funcitons
    > (i.e., void doSomethingTo(Type* thisObject) ).
    >
    > <referece: code below>
    >
    > Is it safe to return a reference to an internally created object? Is
    > obj's destructor called at end of main or at end of fromString()?

    No. It's not safe. Destructor is called at the end of fromString().

    > This is how I uderstand it: o's copy constructor is called with obj as
    > the arg, and I have avoided a temporary instance of Object.
    >
    > Is this safe?
    >
    > Thanks
    >
    > <code>
    > class Object
    > {
    > public:
    > static Object &fromString(std::string str)

    Should be: static Object fromString(std::string str)
    > {
    > Object obj;
    > //process string, and set attributes of obj
    > return obj;

    This is ungood. obj is destroyed at the end of fromString
    Scott Meyers has a good discussion of this in Effective C++, where he points
    out that while return by reference is nice for efficiency, there are cases
    (such as this one) where you need to return by value.

    > }
    > };
    >
    > int main()
    > {
    > Object o = Object::fromString("attribute1,attribute2");
    > cout << "att1 is " << o.getAtt1()
    > << "att2 is " << o.getAtt1()
    > << "att3 is " << o.getAtt1() << endl;
    > }
    > </code>



    It's essentially the equivalent of the C construct:

    int *f()
    {
    int x;
    return &x;
    }

    When you return from f, the pointer is invalid. Similarly, when you return from fromString, the
    reference doesn't refer to anything valid.

    red floyd
     
    red floyd, Oct 8, 2003
    #2
    1. Advertising

  3. Shea Martin

    jeffc Guest

    "Shea Martin" <> wrote in message
    news:4JXgb.6802$f7.391628@localhost...
    > Trying to avoid a temp object, and c-style funcitons
    > (i.e., void doSomethingTo(Type* thisObject) ).
    >
    > <referece: code below>
    >
    > Is it safe to return a reference to an internally created object?


    Sometimes.

    > Is obj's destructor called at end of main or at end of fromString()?


    Yes. This isn't one of those times :)
    >
    > This is how I uderstand it: o's copy constructor is called with obj as
    > the arg, and I have avoided a temporary instance of Object.


    There is no obj to use as an arg, since as you guessed it was destroyed
    after leaving fromString.
     
    jeffc, Oct 8, 2003
    #3
  4. Shea Martin

    Rolf Magnus Guest

    Shea Martin wrote:

    > Trying to avoid a temp object, and c-style funcitons
    > (i.e., void doSomethingTo(Type* thisObject) ).
    > <referece: code below>
    >
    > Is it safe to return a reference to an internally created object?


    No.

    > Is obj's destructor called at end of main or at end of fromString()?


    At the end of fromString().

    > This is how I uderstand it: o's copy constructor is called with obj
    > as the arg, and I have avoided a temporary instance of Object.


    Wrong.

    > Is this safe?
    >
    > Thanks
    >
    > <code>
    > class Object
    > {
    > public:
    > static Object &fromString(std::string str)


    You have to return an Object, not a reference. Btw, the above will copy
    the std::string, so you should use a reference here:

    static Object fromString(const std::string& str)

    Btw, a good compiler optimzies the extra copy of function return values
    away.

    > {
    > Object obj;
    > //process string, and set attributes of obj
    > return obj;
    > }
    > };
    >
    > int main()
    > {
    > Object o = Object::fromString("attribute1,attribute2");
    > cout << "att1 is " << o.getAtt1()
    > << "att2 is " << o.getAtt1()
    > << "att3 is " << o.getAtt1() << endl;
    > }
    > </code>
     
    Rolf Magnus, Oct 8, 2003
    #4
  5. Shea Martin

    jeffc Guest

    "Rolf Magnus" <> wrote in message
    news:bm1sh8$d4n$04$-online.com...
    > > static Object &fromString(std::string str)

    >
    > You have to return an Object, not a reference.


    You can return a reference as long as the object is allocated dynamically.
    This puts the responsibility for the object (deletion) with the caller.
     
    jeffc, Oct 8, 2003
    #5
  6. > Trying to avoid a temp object, and c-style funcitons
    > (i.e., void doSomethingTo(Type* thisObject) ).


    Good idea, but sometimes you can't.

    > <referece: code below>
    >
    > Is it safe to return a reference to an internally created object?


    No.

    > Is
    > obj's destructor called at end of main or at end of fromString()?


    Yes, when it gets out of scope, it is destroyed.

    > This is how I uderstand it: o's copy constructor is called with obj as
    > the arg, and I have avoided a temporary instance of Object.


    It didn't have the time! 'obj' was destroyed before 'o' was ever aware
    of its existence.

    > Is this safe?


    No! 'Well it works on my computer'. That's bad since you'll have a lot of
    troubles finding why it crashes 5 minutes (or an hour) after. This would
    be called undefined behavior.

    > <code>
    > class Object
    > {
    > public:
    > static Object &fromString(std::string str)


    Never, never return a reference to something if that something did not exist
    prior entering a function (except for dynamically allocated memory, but then
    I hope you'll go for pointers.

    > {
    > Object obj;


    'obj' is created here.

    > //process string, and set attributes of obj
    > return obj;
    > }


    'obj' is destroyed there.

    > };
    >
    > int main()
    > {
    > Object o = Object::fromString("attribute1,attribute2");


    fromString() returns a reference to an already destroyed object.
    Undefined behavior. Don't do that!

    When you want to return a object which was inexistant, do it
    by value. You have got no other choices (except for dynamically
    allocated memory, which is always something to avoid).


    Jonathan
     
    Jonathan Mcdougall, Oct 8, 2003
    #6
  7. Shea Martin

    jeffc Guest

    "Jonathan Mcdougall" <> wrote in message
    news:cf%gb.99325$...
    > > public:
    > > static Object &fromString(std::string str)

    >
    > Never, never return a reference to something if that something did not

    exist
    > prior entering a function (except for dynamically allocated memory, but

    then
    > I hope you'll go for pointers.


    Why would you recommend pointers rather than references in that case?
     
    jeffc, Oct 8, 2003
    #7
  8. > > > public:
    > > > static Object &fromString(std::string str)

    > >
    > > Never, never return a reference to something if that something did not

    > exist
    > > prior entering a function (except for dynamically allocated memory, but

    > then
    > > I hope you'll go for pointers.

    >
    > Why would you recommend pointers rather than references in that case?


    Because it makes more sense :

    int &f()
    {
    return *new int;
    }

    int *g()
    {
    return new int;
    }


    int main()
    {
    int &a = f();
    int *b = g();

    delete &a; // yurk
    delete b;
    }


    Jonathan
     
    Jonathan Mcdougall, Oct 8, 2003
    #8
    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. Andrew Fleet

    Returning reference to an array

    Andrew Fleet, Oct 25, 2003, in forum: Perl
    Replies:
    1
    Views:
    463
    Eric J. Roode
    Oct 26, 2003
  2. Ken
    Replies:
    3
    Views:
    9,906
    John C. Bollinger
    Jun 1, 2004
  3. PGR
    Replies:
    6
    Views:
    407
    Stefan Ram
    Jan 4, 2006
  4. Replies:
    11
    Views:
    701
    Christos Georgiou
    May 2, 2006
  5. JustMe
    Replies:
    1
    Views:
    190
    Tassilo v. Parseval
    Aug 29, 2003
Loading...

Share This Page