Initialization lists and optimization

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Marcin Kalicinski

    Initialization lists and optimization

    Hi all,

    struct S
    {
    int x;
    S(int y): x(y) { } // 1
    S(int y) { x = y; } // 2
    }

    Is there any difference between 1 and 2 regarding code optimizations that
    the compiler may apply?

    Best regards,
    Marcin



  • JKop

    #2
    Re: Initialization lists and optimization

    Marcin Kalicinski posted:
    [color=blue]
    > Hi all,
    >
    > struct S
    > {
    > int x;
    > S(int y): x(y) { } // 1
    > S(int y) { x = y; } // 2
    > }
    >
    > Is there any difference between 1 and 2 regarding code optimizations that
    > the compiler may apply?
    >
    > Best regards,
    > Marcin[/color]


    Not of which I am aware. I believe the sole reason that we have the first
    form is for the initialization of const objects and references, eg.

    struct S
    {
    const int x;
    S(int y) : x(y) { } //1
    S(int y) { x = y } //2 Compile ERROR
    };


    As for one being more efficient than the other, I can't think of any reason
    off the top of my head.


    -JKop

    Comment

    • Jeff Flinn

      #3
      Re: Initialization lists and optimization


      "JKop" <NULL@NULL.NULL > wrote in message
      news:XSWCc.3165 $Z14.3784@news. indigo.ie...[color=blue]
      > Marcin Kalicinski posted:
      >[color=green]
      > > Hi all,
      > >
      > > struct S
      > > {
      > > int x;
      > > S(int y): x(y) { } // 1
      > > S(int y) { x = y; } // 2
      > > }
      > >
      > > Is there any difference between 1 and 2 regarding code optimizations[/color][/color]
      that[color=blue][color=green]
      > > the compiler may apply?[/color][/color]

      [snip]
      [color=blue]
      > As for one being more efficient than the other, I can't think of any[/color]
      reason[color=blue]
      > off the top of my head.[/color]

      Writing:

      S::S( int y ){ x = y; }

      Actually is processed as:

      S::S( int y ):x(){ x = y; }

      So you are default(or is it value) initializing, then assigning a value.
      Which is less efficient than:

      S::S( int y ):x(y){}

      Jeff F


      Comment

      • Sumit Rajan

        #4
        Re: Initialization lists and optimization


        "JKop" <NULL@NULL.NULL > wrote in message
        news:XSWCc.3165 $Z14.3784@news. indigo.ie...
        [color=blue]
        > As for one being more efficient than the other, I can't think of any[/color]
        reason[color=blue]
        > off the top of my head.[/color]

        The FAQ addresses this


        Regards,
        Sumit.


        Comment

        • Mike Wahler

          #5
          Re: Initialization lists and optimization


          "Marcin Kalicinski" <kalita@poczta. onet.pl> wrote in message
          news:cbh9u2$c6r $1@korweta.task .gda.pl...[color=blue]
          > Hi all,
          >
          > struct S
          > {
          > int x;
          > S(int y): x(y) { } // 1
          > S(int y) { x = y; } // 2
          > }
          >
          > Is there any difference between 1 and 2 regarding code optimizations that
          > the compiler may apply?[/color]

          The compiler may apply any optimizations at all, as
          long as the 'as if' rule is observed.

          But note that // 1 and // 2 above express different things.
          The former initializes the member 'x', the latter does not,
          but assigns 'x' a value after it is created.

          This can make a difference:

          S(int y) : x(y)
          {
          int i = x; /* OK, 'x' has a value */
          }

          S(int y)
          {
          /* suppose we forget to assign 'x' a value */

          int i = x; /* OOPS, undefined behavior */
          }

          Also the intitialization-list form is required for certain
          things, such as initialization of const or reference members,
          or base class portions of objects.


          -Mike


          Comment

          • Mike Wahler

            #6
            Re: Initialization lists and optimization


            "Jeff Flinn" <NONONE@nowhere .com> wrote in message
            news:cbheua$dd8 $1@bluegill.adi .com...[color=blue]
            >
            > "JKop" <NULL@NULL.NULL > wrote in message
            > news:XSWCc.3165 $Z14.3784@news. indigo.ie...[color=green]
            > > Marcin Kalicinski posted:
            > >[color=darkred]
            > > > Hi all,
            > > >
            > > > struct S
            > > > {
            > > > int x;
            > > > S(int y): x(y) { } // 1
            > > > S(int y) { x = y; } // 2
            > > > }
            > > >
            > > > Is there any difference between 1 and 2 regarding code optimizations[/color][/color]
            > that[color=green][color=darkred]
            > > > the compiler may apply?[/color][/color]
            >
            > [snip]
            >[color=green]
            > > As for one being more efficient than the other, I can't think of any[/color]
            > reason[color=green]
            > > off the top of my head.[/color]
            >
            > Writing:
            >
            > S::S( int y ){ x = y; }
            >
            > Actually is processed as:
            >
            > S::S( int y ):x(){ x = y; }[/color]

            No. (well a compiler is not disallowed from doing
            it that way, but it's not required).

            'x' is not necessarily initialized prior to entering
            the constructor body. The only time that would be
            guaranteed to happen is if 'x' were of a user-defined
            type with a default constructor (type 'int' is not).
            [color=blue]
            >
            > So you are default(or is it value) initializing, then assigning a value.
            > Which is less efficient than:
            >
            > S::S( int y ):x(y){}[/color]

            The efficiency of one form over another is implementation-dependent.

            -Mike


            Comment

            • Siemel Naran

              #7
              Re: Initialization lists and optimization

              "Jeff Flinn" <NONONE@nowhere .com> wrote in message news:cbheua$dd8
              [color=blue]
              > Writing:
              >
              > S::S( int y ){ x = y; }
              >
              > Actually is processed as:
              >
              > S::S( int y ):x(){ x = y; }
              >
              > So you are default(or is it value) initializing, then assigning a value.
              > Which is less efficient than:
              >
              > S::S( int y ):x(y){}[/color]

              Not true. In the first initialization, the system does call the default
              constructor for user defined types like std::string, and thus it is only
              less efficient when your class holds a std::string or other user type. But
              for fundamental types like int, the system does not call the default
              constructor, and thus it does not call the default constructor for x. Thus
              both methods are equivalent, and compilers typically handle both ways
              exactly the same. This rule is present for historical reasons. Exception:
              if the instance of the object you declare is at static or global scope, then
              the system does call the default constructor of fundamental types (but it
              does not for an S object declared as a local variable).


              Comment

              • Siemel Naran

                #8
                Re: Initialization lists and optimization

                "Mike Wahler" <mkwahler@mkwah ler.net> wrote in message news:03YCc.602
                [color=blue][color=green]
                > > S::S( int y ):x(){ x = y; }[/color]
                >
                > No. (well a compiler is not disallowed from doing
                > it that way, but it's not required).[/color]

                For user types, class x may not even have a default constructor, so in
                general the compiler cannot do it this way.
                [color=blue]
                > 'x' is not necessarily initialized prior to entering
                > the constructor body. The only time that would be
                > guaranteed to happen is if 'x' were of a user-defined
                > type with a default constructor (type 'int' is not).[/color]

                Not exactly true on "if 'x' were of a user-defined type with a default
                constructor ". 'x' may be a user defined type without a default
                constructor, or any constructors, but it contains objects that have a
                default constructor, so in that case there is a compiler generated default
                constructor that calls the default constructor of the contained objects.

                struct X {
                std::string s;
                };

                S::S(const X& x2) { x = x2; }
                // above inefficient: same as
                S::S(const X& x2) : x() { x = x2; }
                // which is practically same as (though the syntax is illegal in C++)
                S::S(const X& x2) : x.s() { x = x2; }

                Also, if you declare your class S at global or static scope you get zero
                initialization, even if 'x' is a fundamental type. Also a strange rule for
                historical reasons.



                Comment

                • Mike Wahler

                  #9
                  Re: Initialization lists and optimization


                  "Siemel Naran" <SiemelNaran@RE MOVE.att.net> wrote in message
                  news:QuYCc.1349 98$Gx4.39418@bg tnsc04-news.ops.worldn et.att.net...[color=blue]
                  > "Mike Wahler" <mkwahler@mkwah ler.net> wrote in message news:03YCc.602
                  >[color=green][color=darkred]
                  > > > S::S( int y ):x(){ x = y; }[/color]
                  > >
                  > > No. (well a compiler is not disallowed from doing
                  > > it that way, but it's not required).[/color]
                  >
                  > For user types, class x may not even have a default constructor, so in
                  > general the compiler cannot do it this way.
                  >[color=green]
                  > > 'x' is not necessarily initialized prior to entering
                  > > the constructor body. The only time that would be
                  > > guaranteed to happen is if 'x' were of a user-defined
                  > > type with a default constructor (type 'int' is not).[/color]
                  >
                  > Not exactly true on "if 'x' were of a user-defined type with a default
                  > constructor ". 'x' may be a user defined type without a default
                  > constructor, or any constructors, but it contains objects that have a
                  > default constructor, so in that case there is a compiler generated default
                  > constructor that calls the default constructor of the contained objects.[/color]

                  Right. My reply was incomplete. Thanks for the elaboration.
                  [color=blue]
                  >
                  > struct X {
                  > std::string s;
                  > };
                  >
                  > S::S(const X& x2) { x = x2; }
                  > // above inefficient: same as
                  > S::S(const X& x2) : x() { x = x2; }
                  > // which is practically same as (though the syntax is illegal in C++)
                  > S::S(const X& x2) : x.s() { x = x2; }
                  >
                  > Also, if you declare your class S at global or static scope you get zero
                  > initialization, even if 'x' is a fundamental type. Also a strange rule[/color]
                  for[color=blue]
                  > historical reasons.[/color]

                  Also correct. Since OP didn't give context about that, I suppose I
                  should have addressed the 'static vs 'automatic' issue.

                  -Mike


                  Comment

                  • Stephen M. Webb

                    #10
                    Re: Initialization lists and optimization

                    JKop <NULL@NULL.NULL > wrote in message news:<XSWCc.316 5$Z14.3784@news .indigo.ie>...[color=blue]
                    >
                    > struct S
                    > {
                    > const int x;
                    > S(int y) : x(y) { } //1
                    > S(int y) { x = y } //2 Compile ERROR
                    > };
                    >
                    >
                    > As for one being more efficient than the other, I can't think of any reason
                    > off the top of my head.[/color]

                    The second form default-constructs the member 'x' and then calls its
                    assignment operator to copy the value of 'y' into 'x'.

                    If the default constructor or assignment operator of 'x' were to be a
                    heavy-duty operation with side effects, say, allocating memory from
                    the free store, you would notice a difference.


                    Prefer initialization over the default-constructor-and-assignment
                    route where possible.

                    --
                    Stephen M. Webb
                    stephen.webb@br egmasoft.com

                    Comment

                    • Tao Bo

                      #11
                      Re: Initialization lists and optimization


                      "Marcin Kalicinski" <kalita@poczta. onet.pl> дÈëÏûÏ¢ÐÂÎÅ
                      :cbh9u2$c6r$1@k orweta.task.gda .pl...[color=blue]
                      > Hi all,
                      >
                      > struct S
                      > {
                      > int x;
                      > S(int y): x(y) { } // 1
                      > S(int y) { x = y; } // 2
                      > }
                      >
                      > Is there any difference between 1 and 2 regarding code optimizations that
                      > the compiler may apply?
                      >
                      > Best regards,
                      > Marcin
                      >
                      >
                      >[/color]

                      I think it's nothing about optimization, but the tow constructor have
                      different behavior when construct an object. For constructor 1, the x will
                      be initialized before enter

                      constructor, for a statement like

                      S ps = new S(1);

                      the compiler will generate code like

                      ps = operater new (sizeof(S)); // Allocate
                      memory

                      ps->x = 1;

                      ps->S(1);



                      The difference between the two constructor will be very subtle when you
                      construct some more complex object witch in turn contain other objects or
                      you want to make your

                      constructor "exception free". The book "Exceptiona l C++" gives many deep
                      discussion of these two kind of construcors.





                      Tao Bo



                      Comment

                      Working...