Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Testing my knowledge: how many constructors are called

Reply
Thread Tools

Testing my knowledge: how many constructors are called

 
 
AhmedB
Guest
Posts: n/a
 
      08-03-2008
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
 
Reply With Quote
 
 
 
 
raicuandi
Guest
Posts: n/a
 
      08-03-2008
On Aug 3, 2:44*pm, AhmedB <(E-Mail Removed)> 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?..
 
Reply With Quote
 
 
 
 
AhmedB
Guest
Posts: n/a
 
      08-03-2008
On Aug 2, 11:08*pm, blargg <(E-Mail Removed)> wrote:
> In article
> <(E-Mail Removed)>,
>
>
>
> *AhmedB <(E-Mail Removed)> 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
 
Reply With Quote
 
AhmedB
Guest
Posts: n/a
 
      08-03-2008
On Aug 2, 11:54*pm, raicuandi <(E-Mail Removed)> wrote:
> On Aug 3, 2:44*pm, AhmedB <(E-Mail Removed)> 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.
 
Reply With Quote
 
Erik Wikström
Guest
Posts: n/a
 
      08-03-2008
On 2008-08-03 08:54, raicuandi wrote:
> On Aug 3, 2:44 pm, AhmedB <(E-Mail Removed)> 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
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      08-03-2008
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.
 
Reply With Quote
 
AhmedB
Guest
Posts: n/a
 
      08-03-2008
On Aug 3, 4:38*am, Pete Becker <(E-Mail Removed)> wrote:
> On 2008-08-03 06:36:00 -0400, Erik Wikstrm <(E-Mail Removed)> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Is the possible to have all the public constructors of the publicbase class as the constructors of a derived class? Peng Yu C++ 5 09-19-2008 10:19 AM
compiler synthesized constructors/copy constructors/assignment operators Jess C++ 5 06-07-2007 11:09 AM
Copy constructors, de/constructors and reference counts Jeremy Smith C++ 2 08-02-2006 11:25 PM
Constructors that call other Constructors Dave Rudolf C++ 12 02-06-2004 03:26 PM



Advertisments