why visual studio does not optimize constructor in this case

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • George2
    New Member
    • Dec 2007
    • 200

    why visual studio does not optimize constructor in this case

    Hello everyone,


    Why visual studio does not optimize constructor in this case? I do not understand what the MSDN mentioned,

    if use different named object, compiler can not optimize. Why?

    http://msdn2.microsoft .com/en-us/library/ms364057(vs.80) .aspx

    Code:
    #include <stdio.h>
    class RVO
    {
    public:
           
                RVO(){printf("I am in constructor\n");}
                RVO (const RVO& c_RVO) {printf ("I am in copy constructor\n");}
                int mem_var;       
    };
    RVO MyMethod (int i)
    {
                RVO rvo;
                rvo.mem_var = i;
          if (rvo.mem_var == 10)
             return (RVO());
                return (rvo); 
    }
    int main()
    {
                RVO rvo;
                rvo=MyMethod(5);
    }
    Output is,

    I am in constructor
    I am in constructor
    I am in copy constructor

    My expected output is,

    I am in constructor
    I am in constructor


    thanks in advance,
    George
  • chroot
    New Member
    • Nov 2007
    • 13

    #2
    Maybe the compiler would optimize if you wrote (in main)

    Code:
    RVO rvo=MyMethod(5);
    With two lines, the compiler has no other choice then to use the default constructor, then replace with the copy constructor.

    Comment

    • weaknessforcats
      Recognized Expert Expert
      • Mar 2007
      • 9214

      #3
      This is the output I would expect:

      I am in constructor
      I am in constructor
      I am in copy constructor

      because in main():
      [code=cpp]
      RVO rvo;
      [/code]
      has to create an object. Threrefore: I am in constructor
      Then in this call:
      [code=cpp]
      RVO MyMethod (int i)
      {
      RVO rvo;
      }
      [/code]
      has to create an object. Threrefore: I am in constrcutor

      Then the object has to be returned:
      [code=cpp]
      RVO MyMethod (int i)
      { //etc...
      return (rvo);
      }
      [/code]
      That means a copy. Therefore: I am in copy constrcutor.

      Finally, in main():
      [code=cpp]
      rvo=MyMethod(5) ;
      [/code]
      Normally, the copy constructor would be called to create an initialize rvo. However, the optimization (NRVO) allows the compiler to keep the returned object and call it rvo, thereby saving a constrcutor call.

      Beware that the temporary object returned from MyMethod() does not contain any local pointers or references.

      Comment

      • George2
        New Member
        • Dec 2007
        • 200

        #4
        Thanks chroot,


        Originally posted by chroot
        Maybe the compiler would optimize if you wrote (in main)

        Code:
        RVO rvo=MyMethod(5);
        With two lines, the compiler has no other choice then to use the default constructor, then replace with the copy constructor.
        I have tried that when using the alternative method you mentioned, the output is,

        --------------------
        I am in constructor
        I am in copy constructor
        --------------------

        which means it is optimized, cool!

        What do you mean *the compiler has no other choice then to use the default constructor, then replace with the copy constructor*? Could you provide more information please? I am interested to learn from you why using your alternative method will trigger compiler to optimize the code to overcome MSDN sample. :-)


        regards,
        George

        Comment

        • George2
          New Member
          • Dec 2007
          • 200

          #5
          Thanks weaknessforcats ,


          I do not quite understand why compiler could not optimize the case. The object returned from MyMethod() is temporary, and we could invoke the assignment operator the outer rvo, which could save one time to call copy constructor.

          Why compiler can not optimize in this case, could you provide more description please?

          Originally posted by weaknessforcats
          Normally, the copy constructor would be called to create an initialize rvo. However, the optimization (NRVO) allows the compiler to keep the returned object and call it rvo, thereby saving a constrcutor call.

          Beware that the temporary object returned from MyMethod() does not contain any local pointers or references.

          regards,
          George

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            Originally posted by george2
            do not quite understand why compiler could not optimize the case. The object returned from MyMethod() is temporary, and we could invoke the assignment operator the outer rvo, which could save one time to call copy constructor.
            You can't use the assignment operator on a object that's not built yet.

            This is not an assignment:
            [code=cpp]
            RVO rvo=MyMethod(5) ;
            [/code]

            I know, I know, you see the assignment operator but this is not an assignment. It's an initialization. Initialization requires a constructor. NRVO just lets you use the temporary object retured from MyMethod as rvo.

            BTW: This is in every interview I have ever had:
            [code=cpp]
            RVO rvo=MyMethod(5) ;
            rvo=MyMethod(5) ;
            [/code]

            The question is: How many assignments are there. When you answer 2, you have failed the interview.

            Comment

            • George2
              New Member
              • Dec 2007
              • 200

              #7
              I agree with you, weaknessforcats . Let us come back to the original question. :-)


              http://msdn2.microsoft .com/en-us/library/ms364057(vs.80) .aspx

              You can compare sample 1 and sample 4. The only differences as I stated in my original question is, sample 4 uses different return paths and this is the root cause why compiler can not use NRVO to optimize. I do not know and understand why different return paths matters whether or not compiler will do the optimization. Any ideas?

              Originally posted by weaknessforcats
              You can't use the assignment operator on a object that's not built yet.

              This is not an assignment:
              [code=cpp]
              RVO rvo=MyMethod(5) ;
              [/code]

              I know, I know, you see the assignment operator but this is not an assignment. It's an initialization. Initialization requires a constructor. NRVO just lets you use the temporary object retured from MyMethod as rvo.

              BTW: This is in every interview I have ever had:
              [code=cpp]
              RVO rvo=MyMethod(5) ;
              rvo=MyMethod(5) ;
              [/code]

              The question is: How many assignments are there. When you answer 2, you have failed the interview.

              regards,
              George

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                Originally posted by George2
                I do not know and understand why different return paths matters whether or not compiler will do the optimization. Any ideas?
                Code has been generated to return objects from each of the return paths. Which one should be the Named Returned Value?? Path #1, Path #2 or Path #3 ??? In any ambiguous situation, the compiler backs off optimization as unsafe.

                Now I suppose we could philosophize on this but the fact is that's how it works. Other things prevent NRVO and they are in that MSDN topic as well.

                Comment

                • George2
                  New Member
                  • Dec 2007
                  • 200

                  #9
                  Hi weaknessforcats ,


                  I do not understand why different return paths will block compiler from optimization, for each path #1, #2 or #3, compiler could optimize separately by using hidden argument technique, because for each return path, without optimization they all need to create temporary object on return stack.

                  Any ideas why compiler could not optimize?

                  Originally posted by weaknessforcats
                  Code has been generated to return objects from each of the return paths. Which one should be the Named Returned Value?? Path #1, Path #2 or Path #3 ??? In any ambiguous situation, the compiler backs off optimization as unsafe.

                  Now I suppose we could philosophize on this but the fact is that's how it works. Other things prevent NRVO and they are in that MSDN topic as well.

                  regards,
                  George

                  Comment

                  • weaknessforcats
                    Recognized Expert Expert
                    • Mar 2007
                    • 9214

                    #10
                    NRVO does not optimize if there are multiple return paths because it's not the same object every time.

                    Comment

                    • George2
                      New Member
                      • Dec 2007
                      • 200

                      #11
                      Hi weaknessforcats ,


                      I agree it is not the same object instance, but each different object is doing similar things, making a temporary object on the function return stack and assign it to the return value, then destruct the temporary object on function stack. This is the area which NRVO covers, why it could not optimize, I do not know.

                      It is appreciated if you could share some more perpectives. :-)

                      Originally posted by weaknessforcats
                      NRVO does not optimize if there are multiple return paths because it's not the same object every time.

                      regards,
                      George

                      Comment

                      • weaknessforcats
                        Recognized Expert Expert
                        • Mar 2007
                        • 9214

                        #12
                        You said it yourself: each different object.

                        NRVO is Named Returned Value Object. Not Objects.

                        You have to have only one object be the named return value.

                        Comment

                        • George2
                          New Member
                          • Dec 2007
                          • 200

                          #13
                          Hi weaknessforcats ,


                          I am confused. Named Return Value Optimization, is not the same as only one named return value optimization.

                          You can test that if you have two different variable instances, different names for different return paths, NRVO still does not work.

                          I am not sure why there is such limitation. I am not sure whether I have missed or mis-understood some important aspects of NRVO, which blocks my understanding of why multiple return names with multiple return paths blocks compiler from optimization. Any ideas?

                          Originally posted by weaknessforcats
                          You said it yourself: each different object.

                          NRVO is Named Returned Value Object. Not Objects.

                          You have to have only one object be the named return value.

                          regards,
                          George

                          Comment

                          • weaknessforcats
                            Recognized Expert Expert
                            • Mar 2007
                            • 9214

                            #14
                            Originally posted by george2
                            Any ideas?
                            You can research the C++ language spec. Once you find that multiple return pathes prevent NRVO, then you can try to find the ANSI committee C++ design jnotes where that conclusion was reached.

                            You will never get to the bottom of this and what you think about it doesn't count. You need to find hard factual documentation to support your position. Nothing I can say is going to help.

                            Comment

                            • George2
                              New Member
                              • Dec 2007
                              • 200

                              #15
                              Thanks all the same, I appreciate your help all the way.

                              Originally posted by weaknessforcats
                              You can research the C++ language spec. Once you find that multiple return pathes prevent NRVO, then you can try to find the ANSI committee C++ design jnotes where that conclusion was reached.

                              You will never get to the bottom of this and what you think about it doesn't count. You need to find hard factual documentation to support your position. Nothing I can say is going to help.

                              regards,
                              George

                              Comment

                              Working...