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

initialization within constructor

P: n/a
Hi everyone,

Could someone tell us why the below code compiles and works? Is it
legal in the constructor of class B?

Cheers

Ronny

---------------------------------

#include <iostream>

using namespace std;

class a {
int x;
public:
void show() { cout<<x<<endl; }
a(int xx) : x(xx) {}
a() {}
};

class B {
a ma;
public:
B(int xx);
void disp() { ma.show(); }
};

B::B(int xx) {
ma = a(xx);
}
int main() {
B b(3);
b.disp();

return 0;
}

Jun 14 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
rona wrote:
Could someone tell us why the below code compiles and works?
Probably because it's well-formed...
Is it
legal in the constructor of class B?
Yes, why do you ask? What throws you off?
---------------------------------

#include <iostream>

using namespace std;

class a {
int x;
public:
void show() { cout<<x<<endl; }
a(int xx) : x(xx) {}
a() {}
};

class B {
a ma;
public:
B(int xx);
void disp() { ma.show(); }
};

B::B(int xx) {
ma = a(xx);
This is an assignment from a temporary 'a' object (which is in turn
initialised from the 'xx') to the member 'ma'.
}
You could achieve the same effect by doing

B::B(int xx) {
ma = xx;
}

or, even better, by

B::B(int xx) : ma(xx) {
}


int main() {
B b(3);
b.disp();

return 0;
}


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 14 '06 #2

P: n/a
rona wrote:
Hi everyone,

Could someone tell us why the below code compiles
Yes, because there are no compile-time errors.
and works?
That's harder to determine. What are the requirements for the program?
Is it
legal in the constructor of class B?
Yes. See below.

Cheers

Ronny

---------------------------------

#include <iostream>

using namespace std;

class a {
int x;
public:
void show() { cout<<x<<endl; }
a(int xx) : x(xx) {}
a() {}
This is bad because x is left unitialized and could remain so if the
user isn't careful. You probably added it so class B would compile.
};

class B {
a ma;
public:
B(int xx);
void disp() { ma.show(); }
};

B::B(int xx) {
ma = a(xx);
}


This is legal, but you should delete the default constructor for class
a and use an initialization list here (see
http://www.parashift.com/c++-faq-lit...html#faq-10.6). It works
because there is an implicit = operator generated for class a, and you
"convert" the integer xx to an "a" object by creating a temporary
object of type a. (Actually, it would also work if the line read "ma =
xx;" since that same constructor would be called implicitly.)

Cheers! --M

Jun 14 '06 #3

P: n/a
Victor Bazarov wrote:
rona wrote:
Could someone tell us why the below code compiles and works?
Probably because it's well-formed...
Is it
legal in the constructor of class B?


Yes, why do you ask? What throws you off?


Couple of reasons:
1- I knew using a constructor initializer list was the best option.
Eckel's book sounded as if it was the ONLY option. My mistake.
2- Still confused about what happens to the initial storage allocated
to the member ma. When ma is first declared within the class definition
for B, is memory allocated to ma. If yes, what happens to this memory
after "ma = a(xx);" ?

Cheers
---------------------------------

#include <iostream>

using namespace std;

class a {
int x;
public:
void show() { cout<<x<<endl; }
a(int xx) : x(xx) {}
a() {}
};

class B {
a ma;
public:
B(int xx);
void disp() { ma.show(); }
};

B::B(int xx) {
ma = a(xx);


This is an assignment from a temporary 'a' object (which is in turn
initialised from the 'xx') to the member 'ma'.
}


You could achieve the same effect by doing

B::B(int xx) {
ma = xx;
}

or, even better, by

B::B(int xx) : ma(xx) {
}


int main() {
B b(3);
b.disp();

return 0;
}


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


Jun 14 '06 #4

P: n/a
rona wrote:
Victor Bazarov wrote:
rona wrote:
Could someone tell us why the below code compiles and works?
Probably because it's well-formed...
Is it
legal in the constructor of class B?


Yes, why do you ask? What throws you off?


Couple of reasons:
1- I knew using a constructor initializer list was the best option.
Eckel's book sounded as if it was the ONLY option. My mistake.


No big deal. Happy to help.
2- Still confused about what happens to the initial storage allocated
to the member ma. When ma is first declared within the class
definition for B, is memory allocated to ma. If yes, what happens to
this memory after "ma = a(xx);" ?


Memory stays where it is. You have a default c-tor in 'a' which leaves
the 'x' member uninitialised. Just before this statement, 'ma.x' has
indeterminate value (you can examine it in the debugger). Here, two
things happen: a temporary is constructed with 'xx' as the constructor
argument, and the [compiler-generated] assignment operator is called
which invokes the assignment semantics on all members, which for you
means 'ma.x = sometemporaryobject.x'

[..]

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 14 '06 #5

P: n/a

rona wrote:
Hi everyone,

Could someone tell us why the below code compiles and works? Is it
legal in the constructor of class B?

Cheers

Ronny

---------------------------------

#include <iostream>

using namespace std;

class a {
int x;
public:
void show() { cout<<x<<endl; }
a(int xx) : x(xx) {}
a() {}
};

class B {
a ma;
public:
B(int xx);
void disp() { ma.show(); }
};

B::B(int xx) {
ma = a(xx);
}
int main() {
B b(3);
b.disp();

return 0;
}


Use
B::B(int xx): ma(xx) {
}

instead.
you are assigning a temporary object otherwise.

Jun 14 '06 #6

P: n/a
rona wrote:
...
1- I knew using a constructor initializer list was the best option.
Eckel's book sounded as if it was the ONLY option. My mistake.
It would be the only option if class 'a' had no default constructor. But
it does have one.

If you remove the default constructor declaration from 'a' (the 'a() {}'
line), the code will no longer compile and a constructor initializer
list will become the only option of initializing 'ma' from 'B'.
2- Still confused about what happens to the initial storage allocated
to the member ma. When ma is first declared within the class definition
for B, is memory allocated to ma.
Yes, it is allocated. Initialization of that 'b' object begins with the
implicit initialization of 'ma' through a call to the default
constructor of class 'a' (mentioned above). The default constructor of
'a' does nothing, i.e. no physical initialization takes place ('ma'
still contains garbage after it), but conceptually 'ma' is "initialized".
If yes, what happens to this memory after "ma = a(xx);" ?


A temporary object of type 'a' is created and initialized with the
'a::a(int)' constructor. Then this temporary object is copied into 'ma'
using the copy assignment operator 'a& a::operator=(const a&)'. Since
you didn't declare this operator explicitly, the compiler will declare
and define it for you implicitly.

--
Best regards,
Andrey Tarasevich
Jun 15 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.