"Accelerated C++" beginner question.

A

Alf P. Steinbach

* Chris Croughton:
iostream.h was the old (pre-standard) name for it.

Nope.

<iostream.h> from pre-standard days was not standardized
(it could contain anything), and did not provide the modern iostreams.

_No_ compiler will tell you that.

You are provably wrong:

$ c++ -c /tmp/1.cc
In file included from /usr/local/gcc/lib/.../iostream.h:31,
from /tmp/1.cc:1:
/usr/local/gcc/lib/gcc/.../include/c++/3.4.3/backward/backward_warning.h:32:2:
[snip]
or <iostream> instead of the deprecated header <iostream.h>.

I stand corrected.

g++ 3.4.3 (and 3.4.2) is, in other words, incorrect in this regard.

Oh well...
 
P

Peter Kragh

tony_jeffs said:
int& myFun(int& a, int& b) //int& myFun(~~~) makes it an lvalue!
{
a = a+1;
return a;

1)
What do you return here?
}

int main()
{
int x;
int y;
x=6;
y=1;

std::cout <<x; //x==6
myFun(x,y);
std::cout <<x; //x==7 -incr'd by myFun
int& z=myFun(x,y)+=1; // #Line 23
//x==8(No!), myFun==8, then myFun==9

2)
What takes place here? What order?
std::cout <<x; //NO x==9. why?

return 0;
}

Try to answer question 2) first and then 1). Hint: a = x.

I think it would be a good exercise to figure this one out by yourself.
You may get some help by changing the myFun to:

int myFun(int&, int&)

Good luck. If you get stuck, write again.

BR,
Peter
 
I

Ioannis Vranos

Alf said:
Nope.

<iostream.h> from pre-standard days was not standardized
(it could contain anything), and did not provide the modern iostreams.

The standard <iostream> header has never had another name.


These are unneeded technicalities, however as someone else mentioned in this thread, it is
about compiler-specific facilities that are deprecated and not ISO C++ facilities. The
compiler is free to consider some older of its own facilities as deprecated.
 
C

Chris Croughton

* Chris Croughton:

Nope.

<iostream.h> from pre-standard days was not standardized

Well, duh. Everything from pre-standard days was not standardised, by
definition. Did you know that water is wet?
(it could contain anything), and did not provide the modern iostreams.

It could "contain anything", but in practice it generally contained
something close to whatever a previous draft standard (or edition of
Stroustrup) said about iostreams. Some compilers provided iostreams.h
as the implementation of iostream (in other words iostream just included
iostream.h).
The standard <iostream> header has never had another name.

Since there is no standard header published, only specifications for
what must appear in a header of that name, it obviously didn't have
another (or any) name. Indeed, the standard has no requirement that
there be any physical standard header at all, only that using #include
with that name behaves as if the header was included.
#include <iostream.h> is just about the same, except most
compilers will give you a warning telling you its deprecated.

_No_ compiler will tell you that.

You are provably wrong:

$ c++ -c /tmp/1.cc
In file included from /usr/local/gcc/lib/.../iostream.h:31,
from /tmp/1.cc:1:
/usr/local/gcc/lib/gcc/.../include/c++/3.4.3/backward/backward_warning.h:32:2:
[snip]
or <iostream> instead of the deprecated header <iostream.h>.

I stand corrected.

g++ 3.4.3 (and 3.4.2) is, in other words, incorrect in this regard.

How is it incorrect to warn that including a non-standard header is now
deprecated? If it's a non-standard header then it can, as you point
out, do anything it likes. Including warning that using it is
deprecated and a different (and standard) header now provides the
required functionality.

Chris C
 
A

Alf P. Steinbach

* Chris Croughton:
Some compilers provided iostreams.h
as the implementation of iostream (in other words iostream just included
iostream.h).

Although irrelevant that seems to be impossible: <iostream> is required to
provide 'extern' declarations of four objects of standard iostream types; the
pre-standard iostreams didn't have the same functionality for these objects.

Since there is no standard header published, only specifications for
what must appear in a header of that name

Note that those specifications are incompatible with the usual contents
of prestandard <iostream.h>; it would be remarkable if, as you maintain
above, some compiler vendor foresaw the standard and provided standard
<iostream> via <iostream.h> (yes, that's the implication), and then after the
standardization implemented <iostream> in terms of <iostream.h>.

Are you really sure?

How is it incorrect to warn that including a non-standard header is now
deprecated?

I don't know: _that_ is merely meaningless, a warning that sometime in
the future the compiler will stop being of practical value.
 
?

=?ISO-8859-1?Q?Tr0n=B2?=

Peter Kragh wrote:
Try to answer question 2) first and then 1). Hint: a = x.

I think it would be a good exercise to figure this one out by yourself.
You may get some help by changing the myFun to:

int myFun(int&, int&)

Good luck. If you get stuck, write again.

BR,
Peter

I'd just like to add to Peter's remarks here.

Tony, try to think of how you pass things around in the program... And
think that one way isn't just a "fast way to move data around" but is
instead something different.

I also think Peter should have made more of a point over the way you put
3 things (an assignment(?), a function call and a variable alteration
(+=1 alters by adding one - doesn't "increase" like ++)).

I hope this gives you something to think about...
 
C

Chris Croughton

* Chris Croughton:

Although irrelevant that seems to be impossible: <iostream> is required
NOW

to
provide 'extern' declarations of four objects of standard iostream types; the
pre-standard iostreams didn't have the same functionality for these objects.

What part of "pre-standard" do you not understand? They might not have
had exactly the same functionality (in particular they didn't generally
support stream buffers) but the main functionality used by programmers
was the same (istream, ostream; cin, cout, cerr, clog; input and output
operators; formatting; etc.).
Note that those specifications are incompatible with the usual contents
of prestandard <iostream.h>; it would be remarkable if, as you maintain
above, some compiler vendor foresaw the standard and provided standard
<iostream> via <iostream.h> (yes, that's the implication),

Did you not see the drafts? iostream didn't just appear full-blown in
the final standard, it was in at least two of the drafts before then
(N843, for instance, issued a year before the standard was ratified).
and then after the
standardization implemented <iostream> in terms of <iostream.h>.

When the standard came out, they re-implemented iostream.h with the new
functionality (much of which had been flagged as probable in
pre-standard drafts anyway) and had iostream just include iostream.h (or
the other way round, it makes no difference), because most of the
functionality was not all that different.
Are you really sure?
Yes.


I don't know: _that_ is merely meaningless, a warning that sometime in
the future the compiler will stop being of practical value.

How? Or do you think that the non-standard header iostream.h has
practical value after all?

A feature being deprecated means that it is still supported for old code
but new code should not use it. It doesn't mean the same as obsolescent
or obsolete (although it may get to that stage eventually, but the same
is true of anything in the standard, it could change in future
standards).

The point is that older code often used the .h versions of header files
to provide the functionality now provided by the ones without .h. In
most cases the functionality was not noticably different, and in
particular the versions just before the standard were often very close
to the ones after it.

Chris C
 
A

Alf P. Steinbach

* Chris Croughton:
[snip personal attacks]

When the standard came out, they re-implemented iostream.h with the new
functionality (much of which had been flagged as probable in
pre-standard drafts anyway) and had iostream just include iostream.h (or
the other way round, it makes no difference), because most of the
functionality was not all that different.
Are you really sure?

Yes.

In that case a concrete example would be great.

An <iostream.h> that implemented standard iostreams could break a lot of
code.

How? Or do you think that the non-standard header iostream.h has
practical value after all?

A feature being deprecated means that it is still supported for old code
but new code should not use it. It doesn't mean the same as obsolescent
or obsolete (although it may get to that stage eventually, but the same
is true of anything in the standard, it could change in future
standards).

These two paragraphs seem to be inconsistent -- "non-standard" versus
"in the standard" -- please elaborate.
 
T

tony_jeffs

Thanks Peter
It's making a lot of sense now!
myFun()+=1
actually runs myFun() twice, since it is equivalent to
myFun()= myFun()+1

And int& myFun has to be an lvalue, because myFun()+=1 has to refer to
something that is not transient.

What I was trying to prove to myself is that, since myFun() is an
lvalue, I should be able to increment it, but having it re-base itself
on the value of a ==x each time it is called made it difficult to
demonstrate, so I'm pleased to get around this with the following.


...........................
int& myFun(int& a)
{
if (a<8) //Once x reaches 8, myFun becomes an independant entity.
a = a+1;
return a;
}

int main()
{
int x;
x=6;
cout<<"x at beginning= 6 = " <<x<<endl; //
myFun(x); //
cout<<"x, incrd by myFun()= 7 = " <<x<<endl; //x==7
int& z=myFun(x);
cout<<"myFun after being run again = 8 = " <<z<<endl;
cout<<" and again x having itself been incrd by myfun =8= "<<x<<endl;

cout <<"(myFun+=MyFun)==(myFun + myFun), ==8+8 == "<<(myFun(x)
+=myFun
//now that the if clause in myFun() is FALSE, I can prove that

(x))<<endl;
return 0;
}
 
T

tony_jeffs

Darn - I somehow posted that before I'd finished.
so...
I have a==x==8 so the 'if' in myFun() is not actioned.
So myFun() ==8
myFun()+=myFun()
is the same as myFun()= MyFun()+MyFun()
and it equals 8+8
.........................
Before I wrote this, I thought that that proves myFun() (as in my
previous post) is an lvalue, but now I'm not so sure that it does!

Still, I do feel I'm makin' progress :)
Tony
 
P

Peter Kragh

tony_jeffs said:
Thanks Peter
It's making a lot of sense now!
myFun()+=1
actually runs myFun() twice, since it is equivalent to
myFun()= myFun()+1

No! ... I better explain: The original myFun returned a reference (which
is just another name for something else). It returned a, which is itself
a reference to x.

When you write a (very peculiar) statement like this:

int& z=myFun(x,y)+=1; // #Line 23

, you increment x (a) in myFun, returns a reference to it and increment
it again using operator+=. OK, a bit cryptic explanation to a bit
cryptic statement :)

BTW: "myFun() += 1" is NOT the same as "myFun() = myFun() + 1". The
latter involves two operators (operator+ and operator=). The former only
one.
 
C

Chris Croughton

* Chris Croughton:

In that case a concrete example would be great.

$ cat /usr/include/g++/iostream
// -*- C++ -*- forwarding header.
// This file is part of the GNU ANSI C++ Library.

#ifndef __IOSTREAM__
#define __IOSTREAM__
An <iostream.h> that implemented standard iostreams could break a lot of
code.

Only if that code was using some odd features. Basic stream usage
didn't change much, it was the extra functionality like streambuf which
was the main addition. Things like

cerr << "Fatal error: " << errnum << endl;

have worked since the early versions using iostream.h.
These two paragraphs seem to be inconsistent -- "non-standard" versus
"in the standard" -- please elaborate.

First paragraph:

You said that a warning that a non-standard header is deprecated meant
that at some time the compiler would "stop being of practical value."
That implies that you think that the compiler with the deprecated
feature is now "of practical value."

Second paragraph (not related directly to the preceding paragraph):

You seem to misunderstand the meaning of 'deprecated'. It means
"should not now be used" (for instance, the use of malloc/free in C++
is deprecated), it does not mean that it is intended to disappear.

Parenthetical comment to the last point in the second paragraph:

Everything is subject to change, so a deprecated feature may become
obsolescent, obsolete and eventually disappear. This is true for
things in the standard as well, they can become deprecated,
obsolescent and eventually obsolete and be removed..

Chris C
 
A

Alf P. Steinbach

* Chris Croughton:
$ cat /usr/include/g++/iostream
// -*- C++ -*- forwarding header.
// This file is part of the GNU ANSI C++ Library.

#ifndef __IOSTREAM__
#define __IOSTREAM__
#include <iostream.h>
#endif

It would help knowing which compiler this is, but I assume g++ 2.95 or
earlier.

g++ 2.91 (which was the oldest version I found on this computer) did not
implement standard iostreams at all, so you probably need some other example.

$ cat hello.cpp
#include <iostream> // std::wcout
//#include <istream> // <<, std::endl


int main()
{
std::wcout << L"Hello, Chris" << std::endl;
}
$ g++ --version
egcs-2.91.57
$ g++ hello.cpp
hello.cpp: In function `int main()':
hello.cpp:7: undeclared variable `wcout' (first use here)
$

Only if that code was using some odd features. Basic stream usage
didn't change much, it was the extra functionality like streambuf which
was the main addition. Things like

cerr << "Fatal error: " << errnum << endl;

have worked since the early versions using iostream.h.


First paragraph:

You said that a warning that a non-standard header is deprecated meant

No, I did not say that; you have the full exchange between us above.

that at some time the compiler would "stop being of practical value."
That implies that you think that the compiler with the deprecated
feature is now "of practical value."

Second paragraph (not related directly to the preceding paragraph):

You seem to misunderstand the meaning of 'deprecated'. It means
"should not now be used" (for instance, the use of malloc/free in C++
is deprecated), it does not mean that it is intended to disappear.

<iostream.h> is not a deprecated header.

It's not part of the standard.

At all.
 
T

tony_jeffs

Peter Kragh said:
No! ... I better explain: The original myFun returned a reference (which
is just another name for something else). It returned a, which is itself
a reference to x.

Yes, got that :)
When you write a (very peculiar) statement like this:

int& z=myFun(x,y)+=1; // #Line 23

, you increment x (a) in myFun, returns a reference to it and increment
it again using operator+=. OK, a bit cryptic explanation to a bit
cryptic statement :)

OK, I originally expected += to increment myFun, but not x, but I take
your point. It's something I cant easily conceptualise in English, but
can remember!
I think that myFun must be itself kinda a reference to x, so just as
changing x changes the value of myFun, so too changing myFun changes
x, because they're both stored as whatever's in the same address.
BTW: "myFun() += 1" is NOT the same as "myFun() = myFun() + 1". The
latter involves two operators (operator+ and operator=). The former only
one.

You've convinced me. I've managed to write something where the two
give different results.

I think maybe I'm digging too deep into this - but nevertheless, the
following is curious.

x=1;
// Inserting one of these lines at a time into main() gives curious
results

cout<<(myFun(x)=myFun(x)-1); // 2
cout<<(myFun(x)=myFun(x)+0); // 4 (not 3 !!!)
cout<<(myFun(x)=myFun(x)+1); // 4
cout<<(myFun(x)=myFun(x)+2); // 5
cout<<(myFun(x)=myFun(x)+3); // 6


Tony
 
P

Peter Kragh

tony_jeffs said:
x=1;
// Inserting one of these lines at a time into main() gives curious
results

cout<<(myFun(x)=myFun(x)-1); // 2
cout<<(myFun(x)=myFun(x)+0); // 4 (not 3 !!!)
cout<<(myFun(x)=myFun(x)+1); // 4
cout<<(myFun(x)=myFun(x)+2); // 5
cout<<(myFun(x)=myFun(x)+3); // 6

I'm not sure what you're doing here. I get different results (using the
myFun function from your previous post - with a small modification):

#include <iostream>

using namespace std;

int& myFun(int& a)
{
a = a+1;
return a;
}

int main()
{
int x=1;

cout << "\n" << (myFun(x)=myFun(x)-1); // 2
cout << "\n" << (myFun(x)=myFun(x)+0); // 4 (not 3 !!!)
cout << "\n" << (myFun(x)=myFun(x)+1); // 4
cout << "\n" << (myFun(x)=myFun(x)+2); // 5
cout << "\n" << (myFun(x)=myFun(x)+3); // 6
}

I get the following result:

2
4
7
11
16

Lets try to figure out why. Lets take the first statement (you can work
your way through the rest) and break it into steps: myFun(x)=myFun(x)-1

1) myFun(x) // The right one
2) myFun(x) // The left one
3) operator=

The value of x after the above steps (x = 1 to begin with):

1) 2
2) 3
3) 2 (-1)

For the second statement:

1) 3
2) 4
3) 4 (+0)

You do the rest. I don't see anything curious in this. Remember, myFun
returns x.
 
T

tony_jeffs

Peter Kragh said:
I'm not sure what you're doing here. I get different results (using the
myFun function from your previous post - with a small modification):

#include <iostream>

using namespace std;

int& myFun(int& a)
{
a = a+1;
return a;
}

int main()
{
int x=1;

cout << "\n" << (myFun(x)=myFun(x)-1); // 2
cout << "\n" << (myFun(x)=myFun(x)+0); // 4 (not 3 !!!)
cout << "\n" << (myFun(x)=myFun(x)+1); // 4
cout << "\n" << (myFun(x)=myFun(x)+2); // 5
cout << "\n" << (myFun(x)=myFun(x)+3); // 6
}

I get the following result:

2
4
7
11
16

Lets try to figure out why. Lets take the first statement (you can work
your way through the rest) and break it into steps: myFun(x)=myFun(x)-1

1) myFun(x) // The right one
2) myFun(x) // The left one
3) operator=

The value of x after the above steps (x = 1 to begin with):

1) 2
2) 3
3) 2 (-1)

For the second statement:

1) 3
2) 4
3) 4 (+0)

You do the rest. I don't see anything curious in this. Remember, myFun
returns x.


Peter
I get the same result as you using MS Visual C++ 2005 Beta, and follow
your explanation.
But with the same code copied and pasted into MSVC++6, I get
1
3
5
8
12


I think its an oddity in vc6
Here's the full code illustrating what I was trying to say yesterday,
better explained!

#include "stdafx.h"
#include <iostream>
using std::cout;

int& myFun(int& a)
{
a = a+1;
return a;
}

int main()
{
int x=1;
cout << "\n" << (myFun(x)=myFun(x)-1);
x=1;
cout << "\n" << (myFun(x)=myFun(x)+0);
x=1;
cout << "\n" << (myFun(x)=myFun(x)+1);
x=1;
cout << "\n" << (myFun(x)=myFun(x)+2);
x=1;
cout << "\n" << (myFun(x)=myFun(x)+3);
cout <<"\n";
return 0;
}
/*
Output
1
3
3
4
5
in MS VC++6

Output
2
3
4
5
6
in the new Beta

What compiler do you use/recommend?

Thanx
Tony
 
T

TonyJeffs

Peter Kragh said:
I get the following result:

2
4
7
11
16

Peter
(I posted a long reply, but it must've vanished in the ether)
I get the same as you using MSVC++2005 beta, and I follow your logic,
but I get a different result with MSVC++6, even when I copy and paste.
i.e.
1
3
5
8
12

I can't see how it does that.


My original code had x=1; before each cout<< operation
When I do that with your code in MSVC++6, I get
1
3
3
4
5
....which makes no sense to me.
I guess it's something for a microsoft group, though, rather than
here.
I'm sailing through the next few chapters of this book now I got
chapter 4 out the way :)


Tony
 
P

Peter Kragh

TonyJeffs said:
Peter
(I posted a long reply, but it must've vanished in the ether)
I get the same as you using MSVC++2005 beta, and I follow your logic,
but I get a different result with MSVC++6, even when I copy and paste.
i.e.



I can't see how it does that.

Sorry for the late reply. I have been busy...

Your question and results got me thinking... let's see what the standard
has to say:

Chapter 5, §4:
"Between the previous and next sequence point a scalar object shall have
its stored value modified at most once by the evaluation of an expression."

Note: A sequence point is either a ; or a , (comma).

With an example:

i = v[i++]; // the behavior is unspecified.

The way I see it, your compiler is free to decide what to do with a
statement like this:

cout << (myFun(x) = myFun(x) + 3);

Conclusion: This has been in interesting academic exercise, but don't do
this in real life.

I should have thought about this sooner. Soory.
 
T

TonyJeffs

Cheers Peter
I take your point.

I ve been racing ahead in the book, but a huge crevasse is appearing
in my knowledge, so I think I need to go back and REALLY understand
everything in CH4.

-I pretty much do, but it's hard to see the big picture.

Tony
 
O

Old Wolf

Peter said:
Chapter 5, §4:
"Between the previous and next sequence point a scalar object
shall have its stored value modified at most once by the
evaluation of an expression."

Note: A sequence point is either a ; or a , (comma).

This is your note, not the standard text's note !
Actually a sequence point is more complicated than that.
For example, a comma in a function-call list is NOT
a sequence point.
With an example:

i = v[i++]; // the behavior is unspecified.

Actually the behaviour is undefined.
"Unspecified" means there is a finite set of possible outcomes.
"Undefined" means anything could happen, including the program
crashing.

Now, regarding the following function:

int &myFun(int &x)
{
++x;
return x;
}
The way I see it, your compiler is free to decide what to do with a
statement like this:

cout << (myFun(x) = myFun(x) + 3);

In this case, the behaviour is unspecified.

There is a sequence point immediately before and after a
function call, so the updating done by 'myFun' is "protected"
from causing undefined behaviour by those sequence points.

A fun exercise now would be to work out all the possible
values of 'x' ! Here is my rough attempt, assuming x starts
as 0:

1) The first myFun call is evaluated first, so the expression
is equivalent to:

++x;
x = myFun(x) + 3;

which is equivalent to:

++x;
++x;
x = x + 3;

because the second call to myFun() must occur before the assignment.
So x is 5, and the value printed is also 5.

2) The second myFun call is evaluated first, so the expression
is equivalent to:

++x;
myFun(x) = x + 3;

Now we have two choices:

2a) myFun is now evaluated, the original expression is now:

++x;
++x;
x = x + 3;

giving 5 again, and

2b) x is now evaluated:

++x;
myFun(x) = 4;

giving x = 4 and printing 4.
 

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
473,772
Messages
2,569,593
Members
45,108
Latest member
AlbertEste
Top