By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,233 Members | 1,880 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,233 IT Pros & Developers. It's quick & easy.

Initialization notation

P: n/a
Hello,

I'm a little confused about object initialization. According to Stroustrup
(The C++ Programming Language, Special Edition, Section 10.2.3) constructor
arguments should be supplied in one of the following notations:

MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6);

What's curious: the second notation variant is called an "abbreviated form"
of the first notation variant. I dind't find any further references to this
issue.

But... the first notation variant only compiles (Microsoft 7.0 compiler) if
Date has a valid copy constructor - even though it isn't used in the
expression. The assignment operator doesn't seem to be necessary...

The second notation compiles without copy constructor and assignment
operator (both declared private and not defined).

If the second notation really is an abbreviation of the first variant, both
statements should behave the same way...

So what's happening here?

Regards
Thomas

Jul 22 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a

"Thomas Lorenz" <Lo******@gmx.de> wrote in message
news:Xn***************************@198.120.69.11.. .
Hello,

I'm a little confused about object initialization. According to Stroustrup
(The C++ Programming Language, Special Edition, Section 10.2.3) constructor arguments should be supplied in one of the following notations:

MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6);
But... the first notation variant only compiles (Microsoft 7.0 compiler) if Date has a valid copy constructor - even though it isn't used in the
expression. The assignment operator doesn't seem to be necessary...
Standard makes this requirement that even if the copy c'tor is elided by
implementation it should still be accessible. Theoretically MyClass(1, 2, 3)
makes a temporary object which is then copied into instance1, hence copy
c'tor is required. An implemenrtation is free to elide the copy construction
here. Still if the copy c'tor is made private it won't compile. There is no
assignment so assignment operator doesn't come into picture.

The second notation compiles without copy constructor and assignment
operator (both declared private and not defined).


Right, becuase no temporaries are being created and there is no copy
construction too.
-Sharad
Jul 22 '05 #2

P: n/a
"Sharad Kala" <no******************@yahoo.com> wrote in
news:2n************@uni-berlin.de:

"Thomas Lorenz" <Lo******@gmx.de> wrote in message
news:Xn***************************@198.120.69.11.. .
Hello,

I'm a little confused about object initialization. According to
Stroustrup (The C++ Programming Language, Special Edition, Section
10.2.3)

constructor
arguments should be supplied in one of the following notations:

MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6);

But... the first notation variant only compiles (Microsoft 7.0
compiler)

if
Date has a valid copy constructor - even though it isn't used in the
expression. The assignment operator doesn't seem to be necessary...


Standard makes this requirement that even if the copy c'tor is elided
by implementation it should still be accessible. Theoretically
MyClass(1, 2, 3) makes a temporary object which is then copied into
instance1, hence copy c'tor is required. An implemenrtation is free to
elide the copy construction here. Still if the copy c'tor is made
private it won't compile. There is no assignment so assignment
operator doesn't come into picture.


Hmmm... this means Stroustrup is wrong. The second notation isn't really an
abbreviation of th first notation, since it doesn't impose any restrictions
on the class (except the existance of the used constructor ;)

I really don't see why the standard demands the copy constructor... The
first notation looks like...

1.) Create an instance of MyClass using the default constructor
2.) Create a temporary instance using the parametrized constructor
3.) Assign the result of 2.) to 1.)

As I said - that's how it _looks_ like. If I'd write something nonsensical
like

MyClass instance1(MyClass(1,2,3));

I'd see how the copy constructor would come into play...

So - am I missing something about copy constructors and assignment
operators?

Jul 22 '05 #3

P: n/a

"Thomas Lorenz" <Lo******@gmx.de> wrote in message
news:Xn***************************@198.120.69.11.. .
"Sharad Kala" <no******************@yahoo.com> wrote in
news:2n************@uni-berlin.de: Hmmm... this means Stroustrup is wrong. The second notation isn't really an

I am damn sure that won't be the case. Perhaps you are misinterpreting the
context.
abbreviation of th first notation, since it doesn't impose any restrictions on the class (except the existance of the used constructor ;)

I really don't see why the standard demands the copy constructor... The
first notation looks like...

1.) Create an instance of MyClass using the default constructor
Incorrect. We are first making the temporary using the constructor taking
three ints as parameter. In fact compiler generates no default c'tor for you
in this case.
2.) Create a temporary instance using the parametrized constructor
That's step 1.
3.) Assign the result of 2.) to 1.)
Nope, there is no assignment. Theoretically the temporary created is then
copied into instance1 using the copy c'tor.
As I said - that's how it _looks_ like. If I'd write something nonsensical
like

MyClass instance1(MyClass(1,2,3));

I'd see how the copy constructor would come into play...

So - am I missing something about copy constructors and assignment
operators?


Perhaps that,
someclass c1 = c2; // No assignment, invokes copy c'tor
c2 = c3; // Assignment

-Sharad
Jul 22 '05 #4

P: n/a
Hi!
MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6); _first_ case, you construct two objects:
instance1 a MyClass object instantiated with the default constructor.
MyClass(1,2,3) a temporary MyClass object instantiated with the constructor
MyClass(int,int,int) (i guess ints).
_second_ case, you construct only one object:
instance2 a MyClass object instantiated with the
MyClass(int,int,int)-constructor!
get it?
What's curious: the second notation variant is called an "abbreviated
form" of the first notation variant. I dind't find any further references
to this issue. Abbreviated in the sense that you use the non-default constructor
MyClass(int,int,int) instantly to instantiate an object named instance2! So
you abbreviate in the sense that no temporary object has to be created.
But... the first notation variant only compiles (Microsoft 7.0 compiler)
if Date has a valid copy constructor - even though it isn't used in the
expression. The assignment operator doesn't seem to be necessary... of course it is used. if you have not defined an assignment operator the
copy-constructor is used instead of the assignment operator -> if this does
not work either, you get a compile error!
The second notation compiles without copy constructor and assignment
operator (both declared private and not defined). this is, because the instance2 object is instantiated with the
MyClass(int,int,int) constructor.
see, run-time example:
1) MyClass instance1 = MyClass(1, 2, 3);
instance1 -> calls MyClass()
temp.obj. MyClass(1,2,3) -> calls MyClass(int,int,int)
assign instance1 temp.obj. MyClass(1,2,3) -> call _assignment_ _op._ or
if not defined, _copy_ _constructor_!!

2) MyClass instance2(1,2,3);
instance2 -> calls MyClass(int,int,int)
If the second notation really is an abbreviation of the first variant,
both statements should behave the same way...

no, see run-time example. hope you get it now. i know the beginning is hard,
but as soon as a assignment is in place, there must always be two objects!

hope, the explanation helps you!

regards,
godfired

Jul 22 '05 #5

P: n/a
Thomas Lorenz wrote:
Hello,

I'm a little confused about object initialization. According to Stroustrup
(The C++ Programming Language, Special Edition, Section 10.2.3) constructor
arguments should be supplied in one of the following notations:

MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6);

What's curious: the second notation variant is called an "abbreviated form"
of the first notation variant. I dind't find any further references to this
issue.

This means that they are equivalent. An implementation may use the copy
constructor instead of the assignment operator as an optimisation since
their meaning of both is equivalent.

But... the first notation variant only compiles (Microsoft 7.0 compiler) if
Date has a valid copy constructor - even though it isn't used in the
expression. The assignment operator doesn't seem to be necessary...

Yes see above. Also (just to know it) if you do not define an assignment
operator a member-copy one is implicitly provided.

The second notation compiles without copy constructor and assignment
operator (both declared private and not defined).


Yes but with another constructor.


Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #6

P: n/a
Ioannis Vranos posted:
Thomas Lorenz wrote:
Hello,

I'm a little confused about object initialization. According to
Stroustrup (The C++ Programming Language, Special Edition, Section
10.2.3) constructor arguments should be supplied in one of the
following notations:

MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6);

What's curious: the second notation variant is called an "abbreviated
form" of the first notation variant. I dind't find any further
references to this issue.

This means that they are equivalent. An implementation may use the copy
constructor instead of the assignment operator as an optimisation since
their meaning of both is equivalent.


If the assignment operator is used in the above AT ALL, then you're not
dealing with a C++ compiler.

Taking the line:

MyClass instance1 = MyClass(1,2,3);

The C++ compiler has two options:

A) Construct a temporary with the constructor arguments 1,2,3. Copy-
construct "instance1" from this temporary. Destroy the temporary.

B) Construct instance1 with the constructor arguments 1,2,3.
If the assignment operator gets involved, burn that compiler.
-JKop
Jul 22 '05 #7

P: n/a
Gottfried Eibner <_gottfried._eibner@_univie._ac._at> wrote in
news:41***********************@usenet.univie.ac.at :
What's curious: the second notation variant is called an "abbreviated
form" of the first notation variant. I dind't find any further
references to this issue.

Abbreviated in the sense that you use the non-default constructor
MyClass(int,int,int) instantly to instantiate an object named
instance2! So you abbreviate in the sense that no temporary object has
to be created.

Ah! Interesting interpretation. Didn't occur to me :) I interpreted
"abbreviation" as "shorthand", implying equivalent in every respect. Like
some other "shorthand" notation the language allows...
But... the first notation variant only compiles (Microsoft 7.0
compiler) if Date has a valid copy constructor - even though it isn't
used in the expression. The assignment operator doesn't seem to be
necessary...

of course it is used. if you have not defined an assignment operator
the copy-constructor is used instead of the assignment operator -> if
this does not work either, you get a compile error!

Nope. The compiler wants the copy constructor. It doesn't matter
if the assignment operator is defined or not - it is never used.

Here's my example code:

#include <iostream>
using namespace std;

class E {
public:
E() : m_s() {cout << "E()" << endl;};
E(const string& s) : m_s(s) {cout << "E('" << s << "')" << endl;};
E(const E& right) : m_s(right.m_s) {cout << "E(const E&)" << endl;};
E& operator=(const E& right) {cout << "E::operator=(const E&)" << endl;
return *this;}
private:
string m_s;
};

int main(int argc, char* argv[])
{

cout << "Notation 1" << endl;
E e1 = E("3");
cout << "Notation 2" << endl;
E e2("4");
cout << "finish" << endl;
}

Output is
Notation 1
E('3')
Notation 2
E('4')
finish

If I move the assignment operator to the 'private' section, the code
compiles and runs just fine. If I move the copy constructor to the
'private' section, the code doesn't compile...

As far as I know,

E e1 = E("3");

is meant to create a temporary instance of E (containing '3'), and copy
said temporary into e1 (using the copy constructor). The compiler probably
eliminates the unnecessary copy-construction of the temporary, but still
requests the presence of the copy constructor.

My confusion really was about the meaning of "abbreviation" in the book.

Thanks for your answer, nonetheless ;)

Thomas
Jul 22 '05 #8

P: n/a

This means that they are equivalent. An implementation may use the copy
constructor instead of the assignment operator as an optimisation since
their meaning of both is equivalent.


Really ? I don't think so. Could you quote the standard to this effect.
Jul 22 '05 #9

P: n/a
Ioannis Vranos <iv*@guesswh.at.grad.com> wrote in
news:ce*********@ulysses.noc.ntua.gr:
Thomas Lorenz wrote:
Hello,

I'm a little confused about object initialization. According to
Stroustrup (The C++ Programming Language, Special Edition, Section
10.2.3) constructor arguments should be supplied in one of the
following notations:

MyClass instance1 = MyClass(1, 2, 3);
MyClass instance2(4, 5, 6);

What's curious: the second notation variant is called an "abbreviated
form" of the first notation variant. I dind't find any further
references to this issue.

This means that they are equivalent. An implementation may use the
copy constructor instead of the assignment operator as an optimisation
since their meaning of both is equivalent.

But they _can't_ really be equivalent. Unless the standard proscribes calls
to copy constructor or assignment operator in the first variant. Only then
would it be possible to use either notation for each variant and achieve
the same results.

At least for my compiler these calls are not equivalent, because notation 1
requires the presence of a copy constructor.
But... the first notation variant only compiles (Microsoft 7.0
compiler) if Date has a valid copy constructor - even though it
isn't used in the expression. The assignment operator doesn't seem to
be necessary...

Yes see above. Also (just to know it) if you do not define an
assignment operator a member-copy one is implicitly provided.

I'm quite aware of that fact :)

The second notation compiles without copy constructor and assignment
operator (both declared private and not defined).


Yes but with another constructor.

No, it uses MyClass(int, int, int) too...

Regards
Thomas
Jul 22 '05 #10

P: n/a
JKop <NU**@NULL.NULL> wrote in news:9h******************@news.indigo.ie:
[...]
If the assignment operator is used in the above AT ALL, then you're not
dealing with a C++ compiler. It doesn't use it. So I'm safe for now...
Taking the line:

MyClass instance1 = MyClass(1,2,3);

The C++ compiler has two options:

A) Construct a temporary with the constructor arguments 1,2,3. Copy-
construct "instance1" from this temporary. Destroy the temporary.

B) Construct instance1 with the constructor arguments 1,2,3.
If the assignment operator gets involved, burn that compiler.


I dug up some old version of the C++ ISO standard on the net (Draft from
December '96): ftp://ftp.maths.warwick.ac.uk/pub/c++/std/cd2/

OK, it's outdated, but I don't want to wait for the book :)

Anyway if you search for the keyword copy-initialization (that's apparently
the term for an expression like 'T x = a'), paragraph 8.5.14 requires the
compiler to enumerate the applicable constructors and choose the best one
through overload resolution (source and destination type are identical).
Than that constructor is called to initialize the object.

So the compiler should do 'MyClass instance1(1,2,3);'.

Well apparently the MS compiler treats copy-initialization with the same
type like a copy-initialization with any other type, which is to create a
temporary, and use the best match constructor to initialize the variable.
Since source and destination type are the same, that would be the copy
constructor. So that's why the compiler wants to see it. Since the standard
allows the elimination of the temporary by direct initialization, it is
never called.

So the compiler does 'MyClass instance1(MyClass(1,2,3));' and drops
temporary and copy constructor call.

So apparently Stroustrup is right, and the compiler is wrong...

Did I get this right?

Thomas
Jul 22 '05 #11

P: n/a
"Sharad Kala" <no******************@yahoo.com> wrote in
news:2n************@uni-berlin.de:
Hmmm... this means Stroustrup is wrong. The second notation isn't
really

an

I am damn sure that won't be the case. Perhaps you are misinterpreting
the context.


I'm quite sure you're right.
I'm now (almost) sure the compiler got things wrong (see other post in this
thread).

Probably I'll order a copy of the standard. Didn't think it would be useful
in day to day work until now...

Thanks
Thomas
Jul 22 '05 #12

P: n/a
Gottfried Eibner wrote:

But... the first notation variant only compiles (Microsoft 7.0 compiler)
if Date has a valid copy constructor - even though it isn't used in the
expression. The assignment operator doesn't seem to be necessary...

of course it is used. if you have not defined an assignment operator the
copy-constructor is used instead of the assignment operator -> if this does
not work either, you get a compile error!


????
Do you make your own rules or what?
In this question we are dealing with intialization. operator= is *never*
used for initialization. It is always a constructor involved, in this
case the copy constructor.

Initialization and assignment are 2 different things and one needs
to differentiate between them otherwise such nonsense as above emerges.
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #13

P: n/a
Thomas Lorenz wrote:

JKop <NU**@NULL.NULL> wrote in news:9h******************@news.indigo.ie:
[...]
If the assignment operator is used in the above AT ALL, then you're not
dealing with a C++ compiler. It doesn't use it. So I'm safe for now...
Taking the line:

MyClass instance1 = MyClass(1,2,3);

The C++ compiler has two options:

A) Construct a temporary with the constructor arguments 1,2,3. Copy-
construct "instance1" from this temporary. Destroy the temporary.

B) Construct instance1 with the constructor arguments 1,2,3.
If the assignment operator gets involved, burn that compiler.


I dug up some old version of the C++ ISO standard on the net (Draft from
December '96): ftp://ftp.maths.warwick.ac.uk/pub/c++/std/cd2/

OK, it's outdated, but I don't want to wait for the book :)

Anyway if you search for the keyword copy-initialization (that's apparently
the term for an expression like 'T x = a'), paragraph 8.5.14 requires the
compiler to enumerate the applicable constructors and choose the best one
through overload resolution (source and destination type are identical).
Than that constructor is called to initialize the object.

So the compiler should do 'MyClass instance1(1,2,3);'.


No. That constructor can't be used.

In

MyClass instance = MyClass( 1, 2, 3 );

then on the right hand side of the '=' (but beware: this is not an asignment!)
there is a MyClass object. On the left hand side of the '=' there is a MyClass
object. This means: initialize a MyClass object by using another MyClass object.
And the best constructor for such an initialization is the copy constructor.
Thus the compiler treats the above as

MyClass instance( MyClass( 1, 2, 3) );

It really has no other choice. The 'inner' MyClass object is constructed
as usual, using a ctor which takes 3 int.

That much for the theory. But now for practice. The people writing the C++
standard realized that there would be 2 completely different versions:

MyClass instance( 1, 2, 3 );
MyClass instance = MyClass( 1, 2, 3 );

which eventuall lead up to the very same result. Which one to choose is just
a matter of personal writing preference. All would be well, if the second version
wouldn't require much more overhead due to the creation of the temporary. Thus
they explicitely allowed the compiler to optimize version 2 into version 1, even
if both are intentionally *not* equivalent.

Well apparently the MS compiler treats copy-initialization with the same
type like a copy-initialization with any other type, which is to create a
temporary, and use the best match constructor to initialize the variable.
Yep. And it is correct in doing this.
Since source and destination type are the same, that would be the copy
constructor. So that's why the compiler wants to see it. Since the standard
allows the elimination of the temporary by direct initialization, it is
never called.
Yes. And the standard explicitely states, that even if this optimization is
done, the copy constructor has to be accessible.

So the compiler does 'MyClass instance1(MyClass(1,2,3));' and drops
temporary and copy constructor call.

So apparently Stroustrup is right, and the compiler is wrong...
In which way did you reach to that conclusion? What the compiler does
can be described by using the standards document. There is nothing wrong
in what the compiler does.

Did I get this right?

Thomas

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #14

P: n/a
Karl Heinz Buchegger <kb******@gascad.at> wrote in
news:41***************@gascad.at:
Well apparently the MS compiler treats copy-initialization with the
same type like a copy-initialization with any other type, which is to
create a temporary, and use the best match constructor to initialize
the variable.


Yep. And it is correct in doing this.
Since source and destination type are the same, that would be the
copy constructor. So that's why the compiler wants to see it. Since
the standard allows the elimination of the temporary by direct
initialization, it is never called.


Yes. And the standard explicitely states, that even if this
optimization is done, the copy constructor has to be accessible.

So the compiler does 'MyClass instance1(MyClass(1,2,3));' and drops
temporary and copy constructor call.

So apparently Stroustrup is right, and the compiler is wrong...


In which way did you reach to that conclusion? What the compiler does
can be described by using the standards document. There is nothing
wrong in what the compiler does.


By not really thinking through my own argumentation, I guess. I mentally
branched into the wrong case. The compiler apparently _does_ the right
thing.

And according to your reasoning, Stroustrup is right, too. Possibly guilty
of simplification, but right, nonetheless.

Well, thanks for your precise answer to my confused questions. I guess,
that settles the matter.

And thanks to all participants.

Regards
Thomas
Jul 22 '05 #15

P: n/a
Ioannis Vranos wrote in news:ce*********@ulysses.noc.ntua.gr in
comp.lang.c++:

MyClass instance1 = MyClass(1, 2, 3);

This means that they are equivalent. An implementation may use the
copy constructor instead of the assignment operator as an optimisation
since their meaning of both is equivalent.


There is no assignement in the above, only initialization.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #16

P: n/a
Thomas Lorenz wrote:
I'm quite sure you're right.
I'm now (almost) sure the compiler got things wrong (see other post in this
thread).

Probably I'll order a copy of the standard. Didn't think it would be useful
in day to day work until now...


On page 191 the standard mentions such a case. So indeed on assignment
*upon definition* the copy constructor is used.


So

whatever s1;

// ...
whatever x=s1;
is equivalent to
whatever x(s1);

If the original poster wants an assignment to happen after an
initialisation of the object with its default constructor, then he
should do it in the style:
whatever x;

x=s1;
without any additional cost to what he wants to do (but of course with
additional cost to the use of copy constructor directly).


Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #17

P: n/a
Sharad Kala wrote:
This means that they are equivalent. An implementation may use the copy
constructor instead of the assignment operator as an optimisation since
their meaning of both is equivalent.

Really ? I don't think so. Could you quote the standard to this effect.


You are right and I was wrong. It is not up to the compiler to decide.
The standard requires the copy constructor to be used on assignment
*upon definition* (initialisation), which is also the rational thing to do.


Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.