Testing my knowledge: how many constructors are called

Discussion in 'C++' started by AhmedB, Aug 3, 2008.

  1. AhmedB

    AhmedB Guest

    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
     
    AhmedB, Aug 3, 2008
    #1
    1. Advertising

  2. AhmedB

    raicuandi Guest

    On Aug 3, 2:44 pm, AhmedB <> wrote:
    > 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?..
     
    raicuandi, Aug 3, 2008
    #2
    1. Advertising

  3. AhmedB

    AhmedB Guest

    On Aug 2, 11:08 pm, blargg <> wrote:
    > In article
    > <>,
    >
    >
    >
    >  AhmedB <> wrote:
    > > 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
     
    AhmedB, Aug 3, 2008
    #3
  4. AhmedB

    AhmedB Guest

    On Aug 2, 11:54 pm, raicuandi <> wrote:
    > On Aug 3, 2:44 pm, AhmedB <> wrote:
    >
    >
    >
    > > 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.
     
    AhmedB, Aug 3, 2008
    #4
  5. On 2008-08-03 08:54, raicuandi wrote:
    > On Aug 3, 2:44 pm, AhmedB <> wrote:
    >> 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
     
    Erik Wikström, Aug 3, 2008
    #5
  6. 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.
     
    Juha Nieminen, Aug 3, 2008
    #6
  7. AhmedB

    AhmedB Guest

    On Aug 3, 4:38 am, Pete Becker <> wrote:
    > On 2008-08-03 06:36:00 -0400, Erik Wikström <> said:
    >
    >
    >
    > > 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
     
    AhmedB, Aug 3, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave Rudolf
    Replies:
    12
    Views:
    8,303
    Martijn Lievaart
    Feb 6, 2004
  2. Jeremy Smith
    Replies:
    2
    Views:
    589
    Jeremy Smith
    Aug 3, 2006
  3. Jess
    Replies:
    5
    Views:
    609
    Ron Natalie
    Jun 7, 2007
  4. Peng Yu
    Replies:
    5
    Views:
    399
    Juha Nieminen
    Sep 19, 2008
  5. srp113
    Replies:
    3
    Views:
    470
Loading...

Share This Page