Problem understanding automatic objects

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Joe Hesse

    Problem understanding automatic objects

    /*****
    When I run the following program (gnu C++) the address of the automatic
    object 'a'
    in f() is the same as the address of the automatic object 'b' in main().

    I conclude that 'a' in f() is the same object as 'b' in main().

    Is this an error or an optimization?

    Thank you,
    Joe Hesse
    *****/

    #include <iostream>
    using namespace std;

    class X {
    private:
    int x;
    public:
    X(int a = 0) : x(a) {};
    };

    // function returns an X object by value
    X f() {
    X a;
    cout << "&a in f() is " << &a << endl;
    return a;
    }

    int main() {
    X b = f();
    cout << "&b in main() is " << &b << endl;
    return 0;
    }


  • Ron Natalie

    #2
    Re: Problem understanding automatic objects


    "Joe Hesse" <joe_hesse@actc x.com> wrote in message news:3f8d80b0$0 $41291$a1866201 @newsreader.vis i.com...
    [color=blue]
    > When I run the following program (gnu C++) the address of the automatic
    > object 'a'
    > in f() is the same as the address of the automatic object 'b' in main().[/color]

    Thats fine.
    [color=blue]
    >
    > I conclude that 'a' in f() is the same object as 'b' in main().[/color]

    You conclude wrong.
    [color=blue]
    > // function returns an X object by value
    > X f() {
    > X a;
    > cout << "&a in f() is " << &a << endl;
    > return a;
    > }
    >
    > int main() {
    > X b = f();
    > cout << "&b in main() is " << &b << endl;
    > return 0;
    > }[/color]

    b doesn't necessarily exist in main until after f() is called . a in f()
    doesn't exist after f() returns. It is therefore quite possible that the
    same memory is used for both. However, they are NOT the same
    object. The destructor for f()'s a has been run prior to the construction
    of b in main().


    Comment

    • Joe Hesse

      #3
      Re: Problem understanding automatic objects

      Thanks for the reply.
      I created a destructor for class X which prints a message so you know it is
      called.
      The destructor was only called once, not twice.
      I therefore again conclude that they are the same object.
      Thank you,
      Joe Hesse

      "Ron Natalie" <ron@sensor.com > wrote in message
      news:3f8d8171$0 $232$9a6e19ea@n ews.newshosting .com...[color=blue]
      >
      > "Joe Hesse" <joe_hesse@actc x.com> wrote in message[/color]
      news:3f8d80b0$0 $41291$a1866201 @newsreader.vis i.com...[color=blue]
      >[color=green]
      > > When I run the following program (gnu C++) the address of the automatic
      > > object 'a'
      > > in f() is the same as the address of the automatic object 'b' in main().[/color]
      >
      > Thats fine.
      >[color=green]
      > >
      > > I conclude that 'a' in f() is the same object as 'b' in main().[/color]
      >
      > You conclude wrong.
      >[color=green]
      > > // function returns an X object by value
      > > X f() {
      > > X a;
      > > cout << "&a in f() is " << &a << endl;
      > > return a;
      > > }
      > >
      > > int main() {
      > > X b = f();
      > > cout << "&b in main() is " << &b << endl;
      > > return 0;
      > > }[/color]
      >
      > b doesn't necessarily exist in main until after f() is called . a in f()
      > doesn't exist after f() returns. It is therefore quite possible that the
      > same memory is used for both. However, they are NOT the same
      > object. The destructor for f()'s a has been run prior to the[/color]
      construction[color=blue]
      > of b in main().
      >
      >[/color]


      Comment

      • Erik

        #4
        Re: Problem understanding automatic objects

        > /*****[color=blue]
        > When I run the following program (gnu C++) the address of the automatic
        > object 'a'
        > in f() is the same as the address of the automatic object 'b' in main().
        >
        > I conclude that 'a' in f() is the same object as 'b' in main().
        >
        > Is this an error or an optimization?[/color]

        It's an optimization known as Return Value Optimization (RVO), explicitly
        allowed by the standard
        [color=blue]
        >
        > Thank you,
        > Joe Hesse
        > *****/
        >
        > #include <iostream>
        > using namespace std;
        >
        > class X {
        > private:
        > int x;
        > public:
        > X(int a = 0) : x(a) {};
        > };
        >
        > // function returns an X object by value
        > X f() {
        > X a;
        > cout << "&a in f() is " << &a << endl;
        > return a;
        > }
        >
        > int main() {
        > X b = f();
        > cout << "&b in main() is " << &b << endl;
        > return 0;
        > }
        >
        >[/color]


        Comment

        • Ron Natalie

          #5
          Re: Problem understanding automatic objects


          "Joe Hesse" <joe_hesse@actc x.com> wrote in message news:3f8d9111$0 $41283$a1866201 @newsreader.vis i.com...
          [color=blue]
          > I created a destructor for class X which prints a message so you know it is
          > called.
          > The destructor was only called once, not twice.[/color]

          The G++ is defective. Or your destructor bugging is wrong.
          [color=blue]
          > I therefore again conclude that they are the same object.[/color]

          Your conclusions are still INCORRECT.


          Comment

          • Rob Williscroft

            #6
            Re: Problem understanding automatic objects

            Joe Hesse wrote in news:3f8d80b0$0 $41291$a1866201 @newsreader.vis i.com:
            [color=blue]
            > /*****
            > When I run the following program (gnu C++) the address of the
            > automatic object 'a'
            > in f() is the same as the address of the automatic object 'b' in
            > main().
            >
            > I conclude that 'a' in f() is the same object as 'b' in main().
            >
            > Is this an error or an optimization?[/color]


            Its called Named Return Value Optimisation (NRVO). Some details inline.
            [color=blue]
            >
            > Thank you,
            > Joe Hesse
            > *****/
            >
            > #include <iostream>
            > using namespace std;
            >
            > class X {
            > private:
            > int x;
            > public:
            > X(int a = 0) : x(a) {};
            > };
            >
            > // function returns an X object by value
            > X f() {
            > X a;[/color]

            Here "a" (the named return value) has been put into the
            return-value-location (see below).

            [color=blue]
            > cout << "&a in f() is " << &a << endl;
            > return a;
            > }
            >
            > int main() {
            > X b = f();[/color]

            Here "&b" is passed as the return-value-location to f() and f()
            constructs "b" directly.
            [color=blue]
            > cout << "&b in main() is " << &b << endl;
            > return 0;
            > }
            >
            >[/color]

            Note also that NRVO is a special optimization as it iss allowed
            to bypass a copy-constructor even if that constructor has side
            effects (but the copy-ctor must be accesable).

            HTH

            Rob.
            --

            Comment

            • stelios xanthakis

              #7
              Re: Problem understanding automatic objects

              Rob Williscroft <rtw@freenet.RE MOVE.co.uk> wrote in message news:<Xns9415CB A9C6E8AukcoREMO VEfreenetrtw@19 5.129.110.200>. ..[color=blue]
              > Joe Hesse wrote in news:3f8d80b0$0 $41291$a1866201 @newsreader.vis i.com:[color=green]
              > >
              > > I conclude that 'a' in f() is the same object as 'b' in main().
              > >
              > > Is this an error or an optimization?[/color]
              >
              > Its called Named Return Value Optimisation (NRVO). Some details inline.
              >[color=green]
              > > X f() {
              > > X a;[/color]
              >
              > Here "a" (the named return value) has been put into the
              > return-value-location (see below).
              >[color=green]
              > > cout << "&a in f() is " << &a << endl;
              > > return a;
              > > }
              > >
              > > int main() {
              > > X b = f();[/color]
              >
              > Here "&b" is passed as the return-value-location to f() and f()
              > constructs "b" directly.
              >[color=green]
              > > cout << "&b in main() is " << &b << endl;
              > > return 0;
              > > }[/color]
              >
              > Note also that NRVO is a special optimization as it iss allowed
              > to bypass a copy-constructor even if that constructor has side
              > effects (but the copy-ctor must be accesable).
              >[/color]

              That is interesting. So "f()", or any other function which
              uses RVO is actually used as a constructor. Right? Right?

              Except from the case of operator overloading, the only application
              of RVO functions is to be used for chosing an alternative function
              to do the initialization of members 'n stuff. Yes?

              I was thinking: what's the difference between making f() a member
              function instead of an RVO non-member? It seems that the RVO case has
              the advantage of bypassing the normal constructor calls -- an
              authority given by the standard.

              Any other application of RVO, I'm missing?

              Thanks,

              stelios

              Comment

              • Rob Williscroft

                #8
                Re: Problem understanding automatic objects

                stelios xanthakis wrote in news:8a018872.0 310160201.29cb9 9d0
                @posting.google .com:
                [color=blue]
                >
                > That is interesting. So "f()", or any other function which
                > uses RVO is actually used as a constructor. Right? Right?[/color]

                Well that one way of looking at it, though note the word optimization,
                I understand this as meaning optional feature. i.e. a compiler doesn't
                have to do it, but good ones will.

                IIUC optimization also means the compiler doesn't have to do it
                every time, i.e. it isn't required to be consistant about when
                it does the optimization.
                [color=blue]
                >
                > Except from the case of operator overloading, the only application
                > of RVO functions is to be used for chosing an alternative function
                > to do the initialization of members 'n stuff. Yes?
                >[/color]

                No, any function that returns by value can benifit. Typicaly:
                class_type a;
                a = f();
                will require f() to return a temporary which is then assigned with
                operator =( class_type const & ) to a. With RVO/NRVO this temp can
                be constructed directly by f(), an optimization. Also useful in
                expresion's like g(f()); g{}'s temp argument can again be constructed
                directly by f().
                [color=blue]
                > I was thinking: what's the difference between making f() a member
                > function instead of an RVO non-member? It seems that the RVO case has
                > the advantage of bypassing the normal constructor calls -- an
                > authority given by the standard.[/color]

                It does, but as I noted previously the copy-ctor needs to be accesible
                even though it doesn't get called, also because its an optimisation you
                can't use (N)RVO as a way of changing the meaning of your code.
                [color=blue]
                >
                > Any other application of RVO, I'm missing?
                >[/color]

                Its just a Good Thing(tm).

                Rob.
                --

                Comment

                • Joe Hesse

                  #9
                  Re: Problem understanding automatic objects

                  Even though my class X has no copy constructor, it seems like RVO is
                  bypassing a copy constructor.
                  If the copy constructor had a side effect, like turning on a motor, then the
                  optimization prevents the motor from being turned on, and, therefore,
                  the optimization changes the semantics of the program.
                  Since RVO is allowed by the standard, is there a place in the standard that
                  says that observable side effects should not be placed in copy constructors?
                  Thank you,
                  Joe Hesse

                  "Erik" <no@spam.com> wrote in message news:bmk406$qe1 $1@news.lth.se. ..[color=blue][color=green]
                  > > /*****
                  > > When I run the following program (gnu C++) the address of the automatic
                  > > object 'a'
                  > > in f() is the same as the address of the automatic object 'b' in main().
                  > >
                  > > I conclude that 'a' in f() is the same object as 'b' in main().
                  > >
                  > > Is this an error or an optimization?[/color]
                  >
                  > It's an optimization known as Return Value Optimization (RVO), explicitly
                  > allowed by the standard
                  >[color=green]
                  > >
                  > > Thank you,
                  > > Joe Hesse
                  > > *****/
                  > >
                  > > #include <iostream>
                  > > using namespace std;
                  > >
                  > > class X {
                  > > private:
                  > > int x;
                  > > public:
                  > > X(int a = 0) : x(a) {};
                  > > };
                  > >
                  > > // function returns an X object by value
                  > > X f() {
                  > > X a;
                  > > cout << "&a in f() is " << &a << endl;
                  > > return a;
                  > > }
                  > >
                  > > int main() {
                  > > X b = f();
                  > > cout << "&b in main() is " << &b << endl;
                  > > return 0;
                  > > }
                  > >
                  > >[/color]
                  >
                  >[/color]


                  Comment

                  • Karl Heinz Buchegger

                    #10
                    Re: Problem understanding automatic objects



                    Joe Hesse wrote:[color=blue]
                    >
                    > Even though my class X has no copy constructor, it seems like RVO is
                    > bypassing a copy constructor.
                    > If the copy constructor had a side effect, like turning on a motor, then the
                    > optimization prevents the motor from being turned on, and, therefore,
                    > the optimization changes the semantics of the program.
                    > Since RVO is allowed by the standard, is there a place in the standard that
                    > says that observable side effects should not be placed in copy constructors?
                    > Thank you,[/color]

                    No. That's up to you to know.
                    If the compiler is allowed to optimize the cctor away, even if there are
                    side-effects, then it's clear that you should not do this, because the
                    compiler is allowed to silently change the semantics of your program.
                    The standard only says what a compiler is allowed to do and what it is
                    not allowed to do. Which conclusions you draw from that is up to you.

                    From your given example, it seems you are not 100% sure what should
                    and what should not go into a cctor. You first have to ask yourself
                    one thing: What is the intended purpose of a copy constructor?
                    And the answer is: To create an exact copy of a given object.
                    So if your cctor turns on a motor in an object, then the copy is
                    not a 100% copy of the original object (which had the motor turned off),
                    which is against the intention of a cctor. You may get away with it, but
                    you have to be careful.

                    --
                    Karl Heinz Buchegger
                    kbuchegg@gascad .at

                    Comment

                    Working...