Constructor vs Copy Constructor with assignment

405 views
Skip to first unread message

Jeff Connelly

unread,
Aug 23, 2000, 3:00:00 AM8/23/00
to
I saw something in C++ FAQs (Cline) that confused me. Given this
definition:
class A
{
public:
A();
A(const A&);
};

Then if I were to write:
A a1 = a2;

Does the copy constructor get called, or the default operator=, or
both? I tried it in MS VC++ 5 and sure enough the copy constructor
gets called. Is this a standard compiler "optimization", or
convention, or what?

--
Regards,
Jeff


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]


Victor Bazarov

unread,
Aug 23, 2000, 3:00:00 AM8/23/00
to
"Jeff Connelly" <jeff_c...@mgv.com> wrote...

> I saw something in C++ FAQs (Cline) that confused me. Given this
> definition:
> class A
> {
> public:
> A();
> A(const A&);
> };
>
> Then if I were to write:
> A a1 = a2;
>
> Does the copy constructor get called, or the default operator=, or
> both? I tried it in MS VC++ 5 and sure enough the copy constructor
> gets called. Is this a standard compiler "optimization", or
> convention, or what?

That language construct is called "initialization during declaration".

There are two ways:
A a1 = a2; // a2 is of type A
and
A a1(a2); // a2 is of type A

They are equivalent. And for classes they invoke a copy constructor.

Victor
--
Please remove capital A's from my address when replying by mail

JS

unread,
Aug 23, 2000, 3:00:00 AM8/23/00
to
Jeff Connelly <jeff_c...@mgv.com> wrote in message
news:8o11r7$vrb$1...@nnrp1.deja.com...

> I saw something in C++ FAQs (Cline) that confused me. Given this
> definition:
> class A
> {
> public:
> A();
> A(const A&);
> };
>
> Then if I were to write:
> A a1 = a2;
>
> Does the copy constructor get called, or the default operator=, or
> both? I tried it in MS VC++ 5 and sure enough the copy constructor
> gets called. Is this a standard compiler "optimization", or
> convention, or what?
>

Hi Jeff !

May be this code examples will help You:

class B { ... };

class A
{
...
public:
// Constructor
A() { ... }

// Copy constructor
A(const A& a_obj) { ... }

// Constructor overloading
A(const B& b_obj) { ... }
...
A& operator=(const A& a_src) { ... }
...
};

// Code examples:
A a1; // constructor as: A()
A a2(a1); // copy constructor as: A(a1)
A a3 = a2; // copy constructor as: A(a2)

B b;
A a4(b); // overloaded constructor as: A(b)
A a5 = b; // overloaded constructor as: A(b)

a1 = a5; // operator=(const A&) as: operator=(a5)
a2 = b; // first step -> creating temporary object of class A
// by overloaded constructor as: A(b),
// and next step -> operator=(const A&) as:
operator=(A(b))

~~~ Max

Tom

unread,
Aug 24, 2000, 3:00:00 AM8/24/00
to
On 23 Aug 2000 16:48:06 -0400, "Victor Bazarov" <vAba...@dAnai.com>
wrote:

>"Jeff Connelly" <jeff_c...@mgv.com> wrote...


>> I saw something in C++ FAQs (Cline) that confused me. Given this
>> definition:
>> class A
>> {
>> public:
>> A();
>> A(const A&);
>> };
>>
>> Then if I were to write:
>> A a1 = a2;
>>
>> Does the copy constructor get called, or the default operator=, or
>> both? I tried it in MS VC++ 5 and sure enough the copy constructor
>> gets called. Is this a standard compiler "optimization", or
>> convention, or what?
>

>That language construct is called "initialization during declaration".
>
>There are two ways:
> A a1 = a2; // a2 is of type A
>and
> A a1(a2); // a2 is of type A
>
>They are equivalent. And for classes they invoke a copy constructor.

What about
A a1 = A(a2);
?

I like the above syntax since it gets rid of the problem with the
occasional ambiguity between function declarations and constructor
calls.

But from what I could tell from reading the standard, the above is not
guaranteed to not create a temporary. Or am I wrong?

Tom

Francis Glassborow

unread,
Aug 24, 2000, 3:00:00 AM8/24/00
to
In article <8o11r7$vrb$1...@nnrp1.deja.com>, Jeff Connelly
<jeff_c...@mgv.com> writes

>I saw something in C++ FAQs (Cline) that confused me. Given this
>definition:
>class A
>{
>public:
> A();
> A(const A&);
>};
>
>Then if I were to write:
>A a1 = a2;
^
assuming that a2 is of type A (or a cv qualified version) then that is
NOT and NEVER has been an assignment operator, it is an initaliser in a
declarator and is implemented by calling the copy ctor. If a2 is an
instance of something that has an implicit conversion to A via a ctor
taking a single argument it requires an accessible copy ctor as well,
and both copy ctor and single argument ctor must NOT be qualified as
explicit. Under such circumstances the compiler may optimise away the
copy ctor and use the converting ctor to directly construct a1 from a2.

>
>Does the copy constructor get called, or the default operator=, or
>both? I tried it in MS VC++ 5 and sure enough the copy constructor
>gets called. Is this a standard compiler "optimization", or
>convention, or what?

MS VC++ 5 is entirely correct in its behaviour. Write out 100 times:

'Initialisation is not assignment.'

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Martin Fabian

unread,
Aug 24, 2000, 3:00:00 AM8/24/00
to
Victor Bazarov wrote:
>
<snap>


> There are two ways:
> A a1 = a2; // a2 is of type A
> and
> A a1(a2); // a2 is of type A
>
> They are equivalent. And for classes they invoke a copy constructor.
>
But in the case when a2 is _not_ of type A, they are not necessarily
equivalent. In the first case, a temporary A may be constructed from a2,
and this temporary is then used to copy construct a1. In the second
case, the copy constructor need not be invoked at all.

Assuming a2 is of some type from which an A may be constructed, of
course.

--
Martin Fabian http://www.s2.chalmers.se/~fabian/
--
"Cheer up. It may never happen" (Edina Monsoon)

/* Remove NOSPAM from reply-to address to mail me */

Francis Glassborow

unread,
Aug 24, 2000, 3:00:00 AM8/24/00
to
In article <8o1ejv$gar$2...@pumba.cell.ru>, JS <wald...@hotmail.com>
writes

>Jeff Connelly <jeff_c...@mgv.com> wrote in message
>news:8o11r7$vrb$1...@nnrp1.deja.com...
>> I saw something in C++ FAQs (Cline) that confused me. Given this
>> definition:
>> class A
>> {
>> public:
>> A();
>> A(const A&);
>> };
>>
>> Then if I were to write:
>> A a1 = a2;
>>
>> Does the copy constructor get called, or the default operator=, or
>> both? I tried it in MS VC++ 5 and sure enough the copy constructor
>> gets called. Is this a standard compiler "optimization", or
>> convention, or what?
>>
>
>Hi Jeff !
>
>May be this code examples will help You:
>
>class B { ... };
>
>class A
>{
> ...
> public:
> // Constructor
> A() { ... }
>
> // Copy constructor
> A(const A& a_obj) { ... }
>
> // Constructor overloading
> A(const B& b_obj) { ... }
> ...
> A& operator=(const A& a_src) { ... }
> ...
>};
>
>// Code examples:
> A a1; // constructor as: A()
> A a2(a1); // copy constructor as: A(a1)
> A a3 = a2; // copy constructor as: A(a2)
I am not absolutely certain that that one does not require a non-
explicit qualified ctor.

>
> B b;
> A a4(b); // overloaded constructor as: A(b)
> A a5 = b; // overloaded constructor as: A(b)

That one definitely requires an accessible copy ctor that has not been
qualified as explicit even though the compiler is allowed to optimise
away the call to it.



>
> a1 = a5; // operator=(const A&) as: operator=(a5)
> a2 = b; // first step -> creating temporary object of class A
> // by overloaded constructor as: A(b),

Which again must not be qualified as explicit.


> // and next step -> operator=(const A&) as:
>operator=(A(b))
>

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Ron Natalie

unread,
Aug 24, 2000, 3:00:00 AM8/24/00
to

Francis Glassborow wrote:
>
> >Then if I were to write:
> >A a1 = a2;

> ^
> assuming that a2 is of type A (or a cv qualified version) then that is
> NOT and NEVER has been an assignment operator,

I don't even think you need the qualification as to the type of a2. It's
still
copy-initializatoin. a2 of whatever type has to be converted
(implicitly) to
type A and then direct-initialized into a1.

ka...@gabi-soft.de

unread,
Aug 27, 2000, 3:00:00 AM8/27/00
to
Francis Glassborow <fra...@robinton.demon.co.uk> writes:

|> In article <8o11r7$vrb$1...@nnrp1.deja.com>, Jeff Connelly
|> <jeff_c...@mgv.com> writes

|> >I saw something in C++ FAQs (Cline) that confused me. Given this
|> >definition:
|> >class A
|> >{
|> >public:
|> > A();
|> > A(const A&);
|> >};
|> >

|> >Then if I were to write:
|> >A a1 = a2;
|> ^
|> assuming that a2 is of type A (or a cv qualified version) then that

|> is NOT and NEVER has been an assignment operator, it is an


|> initaliser in a declarator and is implemented by calling the copy
|> ctor.

Regardless of the type of a2, there is no assignment operator here. An
assignment operator (like any other operator) only occurs in an
expression -- here, we have a declaration with initialization. (We also
have an expression, but the expression is simply "a2".)

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

ka...@gabi-soft.de

unread,
Aug 27, 2000, 3:00:00 AM8/27/00
to
Martin Fabian <fabian...@s2.chalmers.se> writes:

|> Victor Bazarov wrote:
|> >
|> <snap>

|> > There are two ways:
|> > A a1 = a2; // a2 is of type A
|> > and
|> > A a1(a2); // a2 is of type A

|> > They are equivalent. And for classes they invoke a copy constructor.

|> But in the case when a2 is _not_ of type A, they are not necessarily
|> equivalent.

I the case where a2 is not of type A, they are not equivalent, period.
In some cases, however, the compiler may, practically speaking, generate
the same code for the two.

|> In the first case, a temporary A may be constructed from a2,
|> and this temporary is then used to copy construct a1. In the second
|> case, the copy constructor need not be invoked at all.

In the second, the copy constructor may not be invoked. This is a very
big difference. In the first, the compiler is allowed to elide the copy
constructor, and most do, but the legality of the program must be
determined as if the copy constructor is invoked. If the class doesn't
have an accessible copy constructor, the first form is illegal, whereas
the second isn't.

ka...@gabi-soft.de

unread,
Aug 27, 2000, 3:00:00 AM8/27/00
to
Francis Glassborow <fra...@robinton.demon.co.uk> writes:

|> > B b;
|> > A a4(b); // overloaded constructor as: A(b)
|> > A a5 = b; // overloaded constructor as: A(b)
|> That one definitely requires an accessible copy ctor that has not been
|> qualified as explicit even though the compiler is allowed to optimise
|> away the call to it.

Are you sure? What it definitly requires is that the constructor
A::A(B) not be explicit (whereas the form with () works even if the
constructor is explicit).

Francis Glassborow

unread,
Aug 28, 2000, 3:00:00 AM8/28/00
to
In article <86ya1im...@gabi-soft.de>, ka...@gabi-soft.de writes

>|> assuming that a2 is of type A (or a cv qualified version) then that
>|> is NOT and NEVER has been an assignment operator, it is an
>|> initaliser in a declarator and is implemented by calling the copy
>|> ctor.
>
>Regardless of the type of a2, there is no assignment operator here. An
>assignment operator (like any other operator) only occurs in an
>expression -- here, we have a declaration with initialization. (We also
>have an expression, but the expression is simply "a2".)

Yes, I constructed a very poor sentence, the assumption was needed for
the very last part (copy ctor)


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 28, 2000, 3:00:00 AM8/28/00
to
In article <863djqo...@gabi-soft.de>, ka...@gabi-soft.de writes

>Are you sure? What it definitly requires is that the constructor
>A::A(B) not be explicit (whereas the form with () works even if the
>constructor is explicit).

Well not absolutely because I do not think we have officially tied down
what it means to make a copy ctor explicit, but when we discussed it
briefly at the most recent J16/WG21 meeting I believe that our general
reaction was that an explicit copy ctor would require exactly that the
compiler could never call it implicitly.

John Potter

unread,
Aug 29, 2000, 12:06:39 AM8/29/00
to
On 28 Aug 2000 13:41:55 -0400, Francis Glassborow
<fra...@robinton.demon.co.uk> wrote:

> In article <863djqo...@gabi-soft.de>, ka...@gabi-soft.de writes
> >Are you sure? What it definitly requires is that the constructor
> >A::A(B) not be explicit (whereas the form with () works even if the
> >constructor is explicit).
>
> Well not absolutely because I do not think we have officially tied down
> what it means to make a copy ctor explicit, but when we discussed it
> briefly at the most recent J16/WG21 meeting I believe that our general
> reaction was that an explicit copy ctor would require exactly that the
> compiler could never call it implicitly.

That of course is the question. Pass by value uses the copy ctor. It
is explicit in pass by value. A copy ctor must be present in an
initializer with = form, thus it is explicit. The exception would be
Base b = Derived which could be doing an implicit slice; however, that
is semantically the same as Base b(Derived).

Those are just opinions. When we discussed it on the newsgroup,
explicit on copy ctor was interpreted as anything from meaningless to
prevents slicing to makes it unuasble for anything other than exact
initialization using the () form. I think the only thing that was
agreed upon was that slicing is a conversion which uses the copy
ctor. Explicit prevents implicit conversions and there is usually
no conversion involved in use of a copy ctor.

For all other explicit ctors, there is a way to use them explicitly.
If all uses of the copy ctor are implicit then how does one make it
explicit? Example:

struct B { B () { } explicit B () { } };
struct D : B { };
void f (B);
void g () {
B b;
D d;
f(b); // not allowed?
f(d); // not allowed?
f(B(d)); // still not allowed?
}

It sure would be nice to have an official definition. Implementers
do not seem to know what it means. The only valid advice today is
"don't do that."

John

Francis Glassborow

unread,
Aug 29, 2000, 3:00:00 AM8/29/00
to
In article <39aafee0...@news.csrlink.net>, John Potter
<jpo...@falcon.lhup.edu> writes

>It sure would be nice to have an official definition. Implementers
>do not seem to know what it means. The only valid advice today is
>"don't do that."

When we discussed it in a work group at the last meeting the feeling was
that explicit on a ctor should inhibit pass and return by value and
certainly the case where it is part of a chain of conversions. Now the
case where you are initialising an X as a copy of an X& using assignment
syntax still needs tying down.


Of course we only consider things at the first meeting they are raised
and there maybe all sorts of objections next time round.

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

John Potter

unread,
Aug 29, 2000, 3:00:00 AM8/29/00
to
On 29 Aug 2000 10:08:38 -0400, Francis Glassborow
<fra...@robinton.demon.co.uk> wrote:

> Of course we only consider things at the first meeting they are raised
> and there maybe all sorts of objections next time round.

Understood. Please do consider how one can use the explicit ctor
explicitely.

Reply all
Reply to author
Forward
0 new messages