returning a reference

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Shea Martin

    returning a reference

    Trying to avoid a temp object, and c-style funcitons
    (i.e., void doSomethingTo(T ype* 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::fromStr ing("attribute1 ,attribute2");
    cout << "att1 is " << o.getAtt1()
    << "att2 is " << o.getAtt1()
    << "att3 is " << o.getAtt1() << endl;
    }
    </code>

  • red floyd

    #2
    Re: returning a reference

    Shea Martin wrote:
    [color=blue]
    > Trying to avoid a temp object, and c-style funcitons
    > (i.e., void doSomethingTo(T ype* 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()?[/color]
    No. It's not safe. Destructor is called at the end of fromString().
    [color=blue]
    > 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)[/color]
    Should be: static Object fromString(std: :string str)[color=blue]
    > {
    > Object obj;
    > //process string, and set attributes of obj
    > return obj;[/color]
    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.
    [color=blue]
    > }
    > };
    >
    > int main()
    > {
    > Object o = Object::fromStr ing("attribute1 ,attribute2");
    > cout << "att1 is " << o.getAtt1()
    > << "att2 is " << o.getAtt1()
    > << "att3 is " << o.getAtt1() << endl;
    > }
    > </code>[/color]


    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

    Comment

    • jeffc

      #3
      Re: returning a reference


      "Shea Martin" <smartin@arcis. com> wrote in message
      news:4JXgb.6802 $f7.391628@loca lhost...[color=blue]
      > Trying to avoid a temp object, and c-style funcitons
      > (i.e., void doSomethingTo(T ype* thisObject) ).
      >
      > <referece: code below>
      >
      > Is it safe to return a reference to an internally created object?[/color]

      Sometimes.
      [color=blue]
      > Is obj's destructor called at end of main or at end of fromString()?[/color]

      Yes. This isn't one of those times :-)[color=blue]
      >
      > 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.[/color]

      There is no obj to use as an arg, since as you guessed it was destroyed
      after leaving fromString.


      Comment

      • Rolf Magnus

        #4
        Re: returning a reference

        Shea Martin wrote:
        [color=blue]
        > Trying to avoid a temp object, and c-style funcitons
        > (i.e., void doSomethingTo(T ype* thisObject) ).
        > <referece: code below>
        >
        > Is it safe to return a reference to an internally created object?[/color]

        No.
        [color=blue]
        > Is obj's destructor called at end of main or at end of fromString()?[/color]

        At the end of fromString().
        [color=blue]
        > 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.[/color]

        Wrong.
        [color=blue]
        > Is this safe?
        >
        > Thanks
        >
        > <code>
        > class Object
        > {
        > public:
        > static Object &fromString(std ::string str)[/color]

        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(cons t std::string& str)

        Btw, a good compiler optimzies the extra copy of function return values
        away.
        [color=blue]
        > {
        > Object obj;
        > //process string, and set attributes of obj
        > return obj;
        > }
        > };
        >
        > int main()
        > {
        > Object o = Object::fromStr ing("attribute1 ,attribute2");
        > cout << "att1 is " << o.getAtt1()
        > << "att2 is " << o.getAtt1()
        > << "att3 is " << o.getAtt1() << endl;
        > }
        > </code>[/color]

        Comment

        • jeffc

          #5
          Re: returning a reference


          "Rolf Magnus" <ramagnus@t-online.de> wrote in message
          news:bm1sh8$d4n $04$1@news.t-online.com...[color=blue][color=green]
          > > static Object &fromString(std ::string str)[/color]
          >
          > You have to return an Object, not a reference.[/color]

          You can return a reference as long as the object is allocated dynamically.
          This puts the responsibility for the object (deletion) with the caller.


          Comment

          • Jonathan Mcdougall

            #6
            Re: returning a reference

            > Trying to avoid a temp object, and c-style funcitons[color=blue]
            > (i.e., void doSomethingTo(T ype* thisObject) ).[/color]

            Good idea, but sometimes you can't.
            [color=blue]
            > <referece: code below>
            >
            > Is it safe to return a reference to an internally created object?[/color]

            No.
            [color=blue]
            > Is
            > obj's destructor called at end of main or at end of fromString()?[/color]

            Yes, when it gets out of scope, it is destroyed.
            [color=blue]
            > 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.[/color]

            It didn't have the time! 'obj' was destroyed before 'o' was ever aware
            of its existence.
            [color=blue]
            > Is this safe?[/color]

            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.
            [color=blue]
            > <code>
            > class Object
            > {
            > public:
            > static Object &fromString(std ::string str)[/color]

            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.
            [color=blue]
            > {
            > Object obj;[/color]

            'obj' is created here.
            [color=blue]
            > //process string, and set attributes of obj
            > return obj;
            > }[/color]

            'obj' is destroyed there.
            [color=blue]
            > };
            >
            > int main()
            > {
            > Object o = Object::fromStr ing("attribute1 ,attribute2");[/color]

            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




            Comment

            • jeffc

              #7
              Re: returning a reference


              "Jonathan Mcdougall" <jonathanmcdoug all@DELyahoo.ca > wrote in message
              news:cf%gb.9932 5$282.1682733@w eber.videotron. net...[color=blue][color=green]
              > > public:
              > > static Object &fromString(std ::string str)[/color]
              >
              > Never, never return a reference to something if that something did not[/color]
              exist[color=blue]
              > prior entering a function (except for dynamically allocated memory, but[/color]
              then[color=blue]
              > I hope you'll go for pointers.[/color]

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


              Comment

              • Jonathan Mcdougall

                #8
                Re: returning a reference

                > > > public:[color=blue][color=green][color=darkred]
                > > > static Object &fromString(std ::string str)[/color]
                > >
                > > Never, never return a reference to something if that something did not[/color]
                > exist[color=green]
                > > prior entering a function (except for dynamically allocated memory, but[/color]
                > then[color=green]
                > > I hope you'll go for pointers.[/color]
                >
                > Why would you recommend pointers rather than references in that case?[/color]

                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


                Comment

                Working...