double re, im; re(r), im(i) vs re=r, im=i

H

Hattuari

On page 32 of TC++PL SE is an example of a complex class as follows:

class complex {
double re, im;
public:
complex(double r, double i){re=r; im=i;}
//...
};

On page 262 of TC++PL SE is an example of a complex class as follows:

class complex {
double re, im;
public:
complex(double r, double i):re(r), im(i){}
//...
};

I understand that in the latter the re(r) and im(i) are in the member
initialization list, whereas in the former the re=r; and im=i; are in the
function body of the constructor. What I'm not clear on is the implication
of doing things one way or the other. Also confusing is the difference in
syntax between re=r and re(r). Where is this latter form introduced in the
text? Where can it be used? How is it different from re=r? How should I
read in in English?

--STH
 
A

Alf P. Steinbach

* Hattuari said:
On page 32 of TC++PL SE is an example of a complex class as follows:

class complex {
double re, im;
public:
complex(double r, double i){re=r; im=i;}
//...
};

On page 262 of TC++PL SE is an example of a complex class as follows:

class complex {
double re, im;
public:
complex(double r, double i):re(r), im(i){}
//...
};

I understand that in the latter the re(r) and im(i) are in the member
initialization list, whereas in the former the re=r; and im=i; are in the
function body of the constructor.
Right.


What I'm not clear on is the implication
of doing things one way or the other. Also confusing is the difference in
syntax between re=r and re(r). Where is this latter form introduced in the
text?

Don't know since I don't have the text; presumably you could find that
out yourself?

Where can it be used? How is it different from re=r? How should I
read in in English?

FAQ: <url: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6>.

Not mentioned or prominently mentioned in the FAQ: you should (ideally)
never depend on declaration order to provide some required initialization
order, because it's subtle and easy to forget or misunderstand. This might
mean that you have to use assignment instead of initializers. It might also
mean a redesign from using direct member objects to using pointers, or, even
better, to remove the need for a particular initialization order.
 
C

Cy Edmunds

Hattuari said:
On page 32 of TC++PL SE is an example of a complex class as follows:

class complex {
double re, im;
public:
complex(double r, double i){re=r; im=i;}
//...
};

On page 262 of TC++PL SE is an example of a complex class as follows:

class complex {
double re, im;
public:
complex(double r, double i):re(r), im(i){}
//...
};

I understand that in the latter the re(r) and im(i) are in the member
initialization list, whereas in the former the re=r; and im=i; are in the
function body of the constructor. What I'm not clear on is the implication
of doing things one way or the other. Also confusing is the difference in
syntax between re=r and re(r). Where is this latter form introduced in the
text? Where can it be used? How is it different from re=r? How should I
read in in English?

--STH

I don't have your text so I can't answer any of your questions about where
things might be found.

I would say that member initialization should always be preferred to
assignment in the constructor body if both will work. The key point is that
before your constructor runs, all member variables must be constructed
somehow. If they are classes, running a default constructor first and then
overriding with an assignment could turn out to be slow.

With plain old data types like double it may not be clear why you would use
the syntax re(r). But if your member is a class, it may need constructor
arguments:

class Fred
{
Ethyl m_e;
public:
Fred(int blort) : m_e(blort) {}
};

That explains the re(r) syntax for classes, but how can the same thing work
for plain old data? It's not so strange if you know that in C++ the
following is legal:

int k(5);

It has the same effect as

int k = 5;

So when would you not use member initialization? When you have something
more complicated to do than just copying the constructor arguments:

class Mabel
{
int m_x;
double m_y;
public:
Mabel() {complicated_function_to_set_x_and_y(&m_x, &m_y);}
};

In my code this doesn't come up all that often.
 
H

Hattuari

Don't know since I don't have the text; presumably you could find that
out yourself?

One might also presume that I looked before asking the question. Perhaps I
should simply glean the implication from his passing comment that all
instances of fundamental types are objects in C++.

That doesn't seem to discuss the difference between the two forms presented
in my question.
Not mentioned or prominently mentioned in the FAQ: you should (ideally)
never depend on declaration order to provide some required initialization
order, because it's subtle and easy to forget or misunderstand. This
might
mean that you have to use assignment instead of initializers. It might
also mean a redesign from using direct member objects to using pointers,
or, even better, to remove the need for a particular initialization order.

Yes, I've always found such dependencies to be objectionable. Sometimes
they are necessary, such as when one subsystem relies on a reference to
another for it's initialization data. Sometimes the alternatives are even
worse. At that point I usually document the dependencies and move on.
 
M

Mike Wahler

Hattuari said:
One might also presume that I looked before asking the question.

See pp 247-248, Section 10.4.6 -- Class Objects as Members
(I have 3rd Edition, the page numbers might not match exactly
in your Special Edition).

-Mike
 
H

Hattuari

Cy said:
With plain old data types like double it may not be clear why you would
use the syntax re(r). But if your member is a class, it may need
constructor arguments:

class Fred
{
Ethyl m_e;
public:
Fred(int blort) : m_e(blort) {}
};

That explains the re(r) syntax for classes, but how can the same thing
work for plain old data? It's not so strange if you know that in C++ the
following is legal:

int k(5);

It has the same effect as

int k = 5;

Thanks, that addresses the essence of my question. At this point I can only
take it for granted that it works. A theoretical explanation would be nice.
I don't know if Stroustrup offers one or not. I have to admit I set the
book down for several months, and don't recall all of the discussion in the
previous chapters. Looking in the index, and thumbing through the chapters
has not led me to an explanation.
 
A

Alf P. Steinbach

* Hattuari said:
One might also presume that I looked before asking the question.

What in the world are you talking about?


That doesn't seem to discuss the difference between the two forms presented
in my question.

It does or should -- it is the section of the FAQ dedicated to that
question.

Comments on the FAQ can be sent to Marshall Cline, the FAQ maintainer,
at <url: mailto:[email protected]>.

At least they could, earlier, but he's got an ever increasing amount of
spam to that address.
 
H

Hattuari

Alf said:
It does or should -- it is the section of the FAQ dedicated to that
question.

My question was actually subtler than what is addressed in the FAQ. The FAQ
item has to do with the difference between the two approaches to
constructing the Complex class. I guess I wasn't clear enough since a few
people seem to have assumed I was asking the question addressed in the
item. What I really wanted to know is what exactly does double re; re(r);
mean? I believe the answer is that all fundamental type in C++ are
actually objects. I believe he states as much in Chapter 10. I can't find
it right now. I guess Stroustrup didn't think it important enough to
warrent more than a passing comment.
 
A

Alf P. Steinbach

* Hattuari said:
My question was actually subtler than what is addressed in the FAQ. The FAQ
item has to do with the difference between the two approaches to
constructing the Complex class. I guess I wasn't clear enough since a few
people seem to have assumed I was asking the question addressed in the
item. What I really wanted to know is what exactly does double re; re(r);
mean? I believe the answer is that all fundamental type in C++ are
actually objects. I believe he states as much in Chapter 10. I can't find
it right now. I guess Stroustrup didn't think it important enough to
warrent more than a passing comment.

Well, I don't have the book (except the first edition, long since outdated).

But here's the technical background.


(1)

When T is a type name, the expression


T( ... arguments, if any )


is a value of type T initialized with the given actual arguments as
construction arguments.

When T is a built-in type there is no actual constructor, but the
allowed syntax is _as if_ there were default constructor so that e.g.


int()


means the value 0 of type int. And also _as if_ there were a copy
constructor.



(2)

The notation '=' is a bit more difficult because it has two different
meanings.

First, in declarations '=' can be used instead of constructor notation,
when the constructor takes exactly one argument. In this situation '='
stands for initialization. Initialization is different from assignment
in that with initialization there is no prior value (e.g., no dynamically
allocated memory to be deallocated), whereas with assignment it is assumed
that there is a prior value (e.g., deallocation may have to be done).

For example, in the variable declaration


int x = 7;


'=' is a short notation for initialization, equivalent to


int x( 7 );


using the 'as if' int copy constructor.



(3)

Outside of declarations '=' means assignment, which is different from
initialization in that it is assumed that there is a prior value. For
example,


std::string s = "Hi";


is a pure initialization with no deallocation, equivalent to


std::string s( "Hi" );


whereas


std::string s;

s = "Hi";


is a default initialization (possibly with dynamic allocation) followed
by an assignment (which possibly may have to deallocate something).
 
T

Thomas Tutone

What in the world are you talking about?

Presumably - again - he meant that he looked in the book before asking the
question, so that your advice to consult the book was not well-taken. Or
was your question rhetorical?

Best regards,

Tom
 
M

Mike Wahler

Hattuari said:
My question was actually subtler than what is addressed in the FAQ. The FAQ
item has to do with the difference between the two approaches to
constructing the Complex class. I guess I wasn't clear enough since a few
people seem to have assumed I was asking the question addressed in the
item. What I really wanted to know is what exactly does double re; re(r);
mean?

double re; /* creates object of type 'double', but doesn't give it a value
*/

re(r); /* syntax error */


class X
{
double re;
public:
X(double arg) : re(arg) /* initializes 're' with value of 'arg'
*before* the 'X' object is constructed */
{
re = arg; /* *assigns* value of 'arg' to 're'.
this is *not* initialization */
}
};
I believe the answer is that all fundamental type in C++ are
actually objects.

Well, not exactly, a type is not an object, it defines
the nature of an object.

But I think I understand what you mean:

int x; /* yes, 'x' is an object with type 'int' */

The same is true of C, btw. A good general way to
think of an object is 'region of storage'.
I believe he states as much in Chapter 10. I can't find
it right now. I guess Stroustrup didn't think it important enough to
warrent more than a passing comment.

One cannot grasp C++ from a single reading of that book. IT must
be studied, and the code experimented with. I've had my copy
of that book for a few years now, and still learn from it.
That's "just the way it is." :)

-Mike
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,163
Messages
2,570,897
Members
47,435
Latest member
PhilipBelm

Latest Threads

Top