Testing my knowledge: how many constructors are called

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

    #1

    Testing my knowledge: how many constructors are called

    Hi,

    I wrote this program, compiled it and ran it with the expectation that
    I will get two printed lines (one from each ctor):

    #include <cstdio>
    class A
    {
    public:
    A(int a)
    {
    fprintf(stderr, "A(int a)\n");
    i = a;
    }
    A(const A& a)
    {
    fprintf(stderr, "A(const A& a)\n");
    i = a.i;
    }
    private:
    int i;
    private:
    const A& operator= (const A&)
    {
    }
    };

    int main()
    {
    A a = A(5);
    return 0;
    }

    I only got:

    A(int a)


    So I thought Ok, maybe the compiler is compiling the

    A a = A(5); to be

    A a(5) somehow,

    So I went ahead and changed the code to make the copy constructor
    explicit, as follows:

    #include <cstdio>
    class A
    {
    public:
    A(int a)
    {
    fprintf(stderr, "A(int a)\n");
    i = a;
    }
    explicit A(const A& a)
    {
    fprintf(stderr, "A(const A& a)\n");
    i = a.i;
    }
    private:
    int i;
    private:
    const A& operator= (const A&)
    {
    }
    };

    int main()
    {
    A a = A(5);
    return 0;
    }

    Then I tried compiling the code and got the following:

    test.cc: In function ‘int main()’:
    test.cc:42: error: no matching function for call to ‘A::A(A)’
    test.cc:18: note: candidates are: A::A(int)

    So my question is, if my understanding is correct and this is the
    sequence that is going on:
    1. An A::A(int) constructor is used to convert an int to an A,
    followed by
    2. An A::A(const A&) constructor is used to copy the temporary A
    and this is why I'm getting the compilation error when I make the
    A::A(const A&) explicit, then why am I not getting two printed lines
    in the first case? Is there something else going on here that I'm not
    paying attention to?

    This code is compiled/run on a Suse 10.3 Linux box with gcc/g++
    version 4.2.1.

    Regards,
    Ahmed
  • blargg

    #2
    Re: Testing my knowledge: how many constructors are called

    In article
    <6ca64954-670f-4e7d-9804-ae2bcba88971@1g 2000pre.googleg roups.com>,
    AhmedB <ahmed.badran@g mail.comwrote:
    I wrote this program, compiled it and ran it with the expectation that
    I will get two printed lines (one from each ctor):
    >
    [snipped class A with ctors A( int ) and A( A const& )]
    >
    int main()
    {
    A a = A(5);
    return 0;
    }
    >
    I only got:
    >
    A(int a)
    >
    So I thought Ok, maybe the compiler is compiling the
    >
    A a = A(5); to be
    >
    A a(5) somehow,
    Right, the compiler is allowed to optimize out the temporary and copy
    ctor call.
    So I went ahead and changed the code to make the copy constructor
    explicit, as follows:
    >
    [snip code]
    >
    Then I tried compiling the code and got the following:
    >
    test.cc: In function Œint main()¹:
    test.cc:42: error: no matching function for call to ŒA::A(A)¹
    test.cc:18: note: candidates are: A::A(int)
    The above optimization must not change the semantics. This way, the
    (in)correctness of the code is not affected by this optimization.

    Comment

    • raicuandi

      #3
      Re: Testing my knowledge: how many constructors are called

      On Aug 3, 2:44 pm, AhmedB <ahmed.bad...@g mail.comwrote:
      Hi,
      >
      I wrote this program, compiled it and ran it with the expectation that
      I will get two printed lines (one from each ctor):
      >
      #include <cstdio>
      class A
      {
              public:
              A(int a)
              {
                      fprintf(stderr, "A(int a)\n");
                      i = a;
              }
              A(const A& a)
              {
                      fprintf(stderr, "A(const A& a)\n");
                      i = a.i;
              }
              private:
              int i;
              private:
              const A& operator= (const A&)
              {
              }
      >
      };
      >
      int main()
      {
              A a = A(5);
              return 0;
      >
      }
      >
      I only got:
      >
      A(int a)
      >
      So I thought Ok, maybe the compiler is compiling the
      >
      A a = A(5); to be
      >
      A a(5) somehow,
      >
      So I went ahead and changed the code to make the copy constructor
      explicit, as follows:
      >
      #include <cstdio>
      class A
      {
              public:
              A(int a)
              {
                      fprintf(stderr, "A(int a)\n");
                      i = a;
              }
              explicit A(const A& a)
              {
                      fprintf(stderr, "A(const A& a)\n");
                      i = a.i;
              }
              private:
              int i;
              private:
              const A& operator= (const A&)
              {
              }
      >
      };
      >
      int main()
      {
              A a = A(5);
              return 0;
      >
      }
      >
      Then I tried compiling the code and got the following:
      >
      test.cc: In function ‘int main()’:
      test.cc:42: error: no matching function for call to ‘A::A(A)’
      test.cc:18: note: candidates are: A::A(int)
      >
      So my question is, if my understanding is correct and this is the
      sequence that is going on:
      1. An A::A(int) constructor is used to convert an int to an A,
      followed by
      2. An A::A(const A&) constructor is used to copy the temporary A
      and this is why I'm getting the compilation error when I make the
      A::A(const A&) explicit, then why am I not getting two printed lines
      in the first case? Is there something else going on here that I'm not
      paying attention to?
      >
      This code is compiled/run on a Suse 10.3 Linux box with gcc/g++
      version 4.2.1.
      >
      Regards,
      Ahmed
      This has got to be the most pointless exercise I've seen this week. :)
      Why would anyone *want* an extra copy-constructor?..

      Comment

      • AhmedB

        #4
        Re: Testing my knowledge: how many constructors are called

        On Aug 2, 11:08 pm, blargg <blargg....@gis hpuppy.comwrote :
        In article
        <6ca64954-670f-4e7d-9804-ae2bcba88...@1g 2000pre.googleg roups.com>,
        >
        >
        >
         AhmedB <ahmed.bad...@g mail.comwrote:
        I wrote this program, compiled it and ran it with the expectation that
        I will get two printed lines (one from each ctor):
        >
        [snipped class A with ctors A( int ) and A( A const& )]
        >
        int main()
        {
           A a = A(5);
           return 0;
        }
        >
        I only got:
        >
        A(int a)
        >
        So I thought Ok, maybe the compiler is compiling the
        >
        A a = A(5); to be
        >
        A a(5) somehow,
        >
        Right, the compiler is allowed to optimize out the temporary and copy
        ctor call.
        >
        So I went ahead and changed the code to make the copy constructor
        explicit, as follows:
        >
        [snip code]
        >
        Then I tried compiling the code and got the following:
        >
        test.cc: In function Œint main()¹:
        test.cc:42: error: no matching function for call to ŒA::A(A)¹
        test.cc:18: note: candidates are: A::A(int)
        >
        The above optimization must not change the semantics. This way, the
        (in)correctness of the code is not affected by this optimization.
        Thanks that makes perfect sense, the compiler is optimizing it in one
        path, and sort of un-optimizing it (or more like leaving its semantics
        alone) in the other case, I've even tried using a g++ -O0 before
        posting it, it didn't seem to make a difference either. Thanks for the
        clarification

        Regards,
        Ahmed

        Comment

        • AhmedB

          #5
          Re: Testing my knowledge: how many constructors are called

          On Aug 2, 11:54 pm, raicuandi <raicua...@gmai l.comwrote:
          On Aug 3, 2:44 pm, AhmedB <ahmed.bad...@g mail.comwrote:
          >
          >
          >
          Hi,
          >
          I wrote this program, compiled it and ran it with the expectation that
          I will get two printed lines (one from each ctor):
          >
          #include <cstdio>
          class A
          {
                  public:
                  A(int a)
                  {
                          fprintf(stderr, "A(int a)\n");
                          i = a;
                  }
                  A(const A& a)
                  {
                          fprintf(stderr, "A(const A& a)\n");
                          i = a.i;
                  }
                  private:
                  int i;
                  private:
                  const A& operator= (const A&)
                  {
                  }
          >
          };
          >
          int main()
          {
                  A a = A(5);
                  return 0;
          >
          }
          >
          I only got:
          >
          A(int a)
          >
          So I thought Ok, maybe the compiler is compiling the
          >
          A a = A(5); to be
          >
          A a(5) somehow,
          >
          So I went ahead and changed the code to make the copy constructor
          explicit, as follows:
          >
          #include <cstdio>
          class A
          {
                  public:
                  A(int a)
                  {
                          fprintf(stderr, "A(int a)\n");
                          i = a;
                  }
                  explicit A(const A& a)
                  {
                          fprintf(stderr, "A(const A& a)\n");
                          i = a.i;
                  }
                  private:
                  int i;
                  private:
                  const A& operator= (const A&)
                  {
                  }
          >
          };
          >
          int main()
          {
                  A a = A(5);
                  return 0;
          >
          }
          >
          Then I tried compiling the code and got the following:
          >
          test.cc: In function ‘int main()’:
          test.cc:42: error: no matching function for call to ‘A::A(A)’
          test.cc:18: note: candidates are: A::A(int)
          >
          So my question is, if my understanding is correct and this is the
          sequence that is going on:
          1. An A::A(int) constructor is used to convert an int to an A,
          followed by
          2. An A::A(const A&) constructor is used to copy the temporary A
          and this is why I'm getting the compilation error when I make the
          A::A(const A&) explicit, then why am I not getting two printed lines
          in the first case? Is there something else going on here that I'm not
          paying attention to?
          >
          This code is compiled/run on a Suse 10.3 Linux box with gcc/g++
          version 4.2.1.
          >
          Regards,
          Ahmed
          >
          This has got to be the most pointless exercise I've seen this week. :)
          Why would anyone *want* an extra copy-constructor?..
          Not a matter of *want* but sometimes one wants to check their
          knowledge and understanding with a simple example, and boom they get
          surprised due to the compiler doing some optimization. I'm one of
          those who are interested in _understanding_ how/why things work/don't
          work, rather than taking things for granted and settling for 'that's
          the way it works' type of thought.

          Comment

          • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

            #6
            Re: Testing my knowledge: how many constructors are called

            On 2008-08-03 08:54, raicuandi wrote:
            On Aug 3, 2:44 pm, AhmedB <ahmed.bad...@g mail.comwrote:
            >Hi,
            >>
            >I wrote this program, compiled it and ran it with the expectation that
            >I will get two printed lines (one from each ctor):
            >>
            >#include <cstdio>
            >class A
            >{
            > public:
            > A(int a)
            > {
            > fprintf(stderr, "A(int a)\n");
            > i = a;
            > }
            > A(const A& a)
            > {
            > fprintf(stderr, "A(const A& a)\n");
            > i = a.i;
            > }
            > private:
            > int i;
            > private:
            > const A& operator= (const A&)
            > {
            > }
            >>
            >};
            >>
            >int main()
            >{
            > A a = A(5);
            > return 0;
            >>
            >}
            >>
            >I only got:
            >>
            >A(int a)
            >>
            >So I thought Ok, maybe the compiler is compiling the
            >>
            >A a = A(5); to be
            >>
            >A a(5) somehow,
            >>
            >So I went ahead and changed the code to make the copy constructor
            >explicit, as follows:
            >>
            >#include <cstdio>
            >class A
            >{
            > public:
            > A(int a)
            > {
            > fprintf(stderr, "A(int a)\n");
            > i = a;
            > }
            > explicit A(const A& a)
            > {
            > fprintf(stderr, "A(const A& a)\n");
            > i = a.i;
            > }
            > private:
            > int i;
            > private:
            > const A& operator= (const A&)
            > {
            > }
            >>
            >};
            >>
            >int main()
            >{
            > A a = A(5);
            > return 0;
            >>
            >}
            >>
            >Then I tried compiling the code and got the following:
            >>
            >test.cc: In function ‘int main()’:
            >test.cc:42: error: no matching function for call to ‘A::A(A)’
            >test.cc:18: note: candidates are: A::A(int)
            >>
            >So my question is, if my understanding is correct and this is the
            >sequence that is going on:
            >1. An A::A(int) constructor is used to convert an int to an A,
            >followed by
            >2. An A::A(const A&) constructor is used to copy the temporary A
            >and this is why I'm getting the compilation error when I make the
            >A::A(const A&) explicit, then why am I not getting two printed lines
            >in the first case? Is there something else going on here that I'm not
            >paying attention to?
            >>
            >This code is compiled/run on a Suse 10.3 Linux box with gcc/g++
            >version 4.2.1.
            >>
            >Regards,
            >Ahmed
            >
            This has got to be the most pointless exercise I've seen this week. :)
            Why would anyone *want* an extra copy-constructor?..
            This has got to be the most pointless answer I've seen this week. :)
            Why would anyone *want* to write it?

            Seriously though, if you do not know that the compiler is allowed some
            optimisations which will change the semantics of the language (from what
            one might expect) it is possible to get some nasty surprises.

            --
            Erik Wikström

            Comment

            • Juha Nieminen

              #7
              Re: Testing my knowledge: how many constructors are called

              blargg wrote:
              Right, the compiler is allowed to optimize out the temporary and copy
              ctor call.
              Note that, AFAIK, if the compiler obeys the standard, it will require
              for the copy constructor to be accessible (ie. not private) even if it
              never calls it.

              Comment

              • Pete Becker

                #8
                Re: Testing my knowledge: how many constructors are called

                On 2008-08-03 06:36:00 -0400, Erik Wikström <Erik-wikstrom@telia. comsaid:
                >
                Seriously though, if you do not know that the compiler is allowed some
                optimisations which will change the semantics of the language (from what
                one might expect) it is possible to get some nasty surprises.
                The optimization doesn't change the semantics of the language. If the
                copy constructor has side effects the optimization changes the
                semantics of the program.

                --
                Pete
                Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                Standard C++ Library Extensions: a Tutorial and Reference
                (www.petebecker.com/tr1book)

                Comment

                • AhmedB

                  #9
                  Re: Testing my knowledge: how many constructors are called

                  On Aug 3, 4:38 am, Pete Becker <p...@versatile coding.comwrote :
                  On 2008-08-03 06:36:00 -0400, Erik Wikström <Erik-wikst...@telia. comsaid:
                  >
                  >
                  >
                  Seriously though, if you do not know that the compiler is allowed some
                  optimisations which will change the semantics of the language (from what
                  one might expect) it is possible to get some nasty surprises.
                  >
                  The optimization doesn't change the semantics of the language. If the
                  copy constructor has side effects the optimization changes the
                  semantics of the program.
                  >
                  Agreed, and I went back, made the two constructors non-equivalent in
                  their side effects (setting i) just to test how intelligent the
                  compiler is in its optimization and sure enough it's still calling the
                  A::A(int) and so in this case the optimization vs. the non-
                  optimization will yield different results and nasty surprises if one
                  is not cautious and aware of what's actually going on.

                  -Ahmed

                  Comment

                  • blargg

                    #10
                    Re: Testing my knowledge: how many constructors are called

                    In article
                    <111c526a-d8c5-495e-9c6f-7265e8b45c80@v1 g2000pra.google groups.com>, AhmedB
                    <ahmed.badran@g mail.comwrote:
                    On Aug 3, 4:38=A0am, Pete Becker <p...@versatile coding.comwrote :
                    ...
                    The optimization doesn't change the semantics of the language. If the
                    copy constructor has side effects the optimization changes the
                    semantics of the program.
                    >
                    Agreed, and I went back, made the two constructors non-equivalent in
                    their side effects (setting i) just to test how intelligent the
                    compiler is in its optimization and sure enough it's still calling the
                    A::A(int) and so in this case the optimization vs. the non-
                    optimization will yield different results and nasty surprises if one
                    is not cautious and aware of what's actually going on.
                    It will yield nasty surprises only if one makes a copy constructor that
                    has nasty surprises to begin with. Moral: write the copy constructor
                    properly from the start.

                    Comment

                    Working...