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

Pointer Dereferencing

P: n/a
Hello friends,

Recently I have begun exploring the features that the STL map
collection provides. While learning how it worked, I encountered a
result that confused me. Up until now, I had always been under the
impression that if I had a pointer variable, p which contained the
member "first", I could access this member variable either by:
(*p).first OR p->first . That is, in general I thought p->x was just
shorthand for (*p).x ?

The particular example I was working with was with printing an item
from a map:

map<string,intm ;
m.insert( make_pair( string( "test" ), false ) ) ;

map<string,int>::const_iterator it ;
for ( it = m.begin() ; it != m.end() ; it++ ) {
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work
}

Can anyone render an explanation to put my mind at ease?

Thanks in advance,

Mike

Nov 13 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Cyron wrote:
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work
Does "THIS DOES NOT WORK" mean that it doesn't compile? Some older
compilers (in particular, VC++ 6) had problems compiling operator-in a
class, so some older standard libraries don't provide it. It's supposed
to be there, though.

--

-- Pete
Roundhouse Consulting, Ltd. -- www.versatilecoding.com
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Nov 13 '06 #2

P: n/a
In article <11**********************@m73g2000cwd.googlegroups .com>,
"Cyron" <md*******@yahoo.comwrote:
Hello friends,

Recently I have begun exploring the features that the STL map
collection provides. While learning how it worked, I encountered a
result that confused me. Up until now, I had always been under the
impression that if I had a pointer variable, p which contained the
member "first", I could access this member variable either by:
(*p).first OR p->first . That is, in general I thought p->x was just
shorthand for (*p).x ?

The particular example I was working with was with printing an item
from a map:

map<string,intm ;
m.insert( make_pair( string( "test" ), false ) ) ;

map<string,int>::const_iterator it ;
for ( it = m.begin() ; it != m.end() ; it++ ) {
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work
}

Can anyone render an explanation to put my mind at ease?
As I understand it, in very old compilers the -operator either was
not, or could not be, overloaded. So in that case they are not identical.

--
To send me email, put "sheltie" in the subject.
Nov 13 '06 #3

P: n/a
* Cyron:
>
Recently I have begun exploring the features that the STL map
collection provides. While learning how it worked, I encountered a
result that confused me. Up until now, I had always been under the
impression that if I had a pointer variable, p which contained the
member "first",
Nitpick: a pointer variable does not contain anything else than a
pointer value, but the pointed to object can contain members. Thus,
it's *p that contains the member "first".

I could access this member variable either by:
(*p).first OR p->first . That is, in general I thought p->x was just
shorthand for (*p).x ?
For built-in operations.

An iterator need not be a raw pointer. It can be an object that offers
pointer operations, and then operator-and operator* are two distinct
operations that might be implemented as just displaying respectively
"huh" and "bah" on std::cout... That said, ...

The particular example I was working with was with printing an item
from a map:

map<string,intm ;
m.insert( make_pair( string( "test" ), false ) ) ;

map<string,int>::const_iterator it ;
for ( it = m.begin() ; it != m.end() ; it++ ) {
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work
}
.... a standard library iterator is required to implement p->x to yield
the effect of (*p).x.

Can anyone render an explanation to put my mind at ease?
Your compiler's standard library implementation seems to be broken. But
then, you haven't defined what "does not work" means, and you haven't
shown a complete program (in particular which headers you have included,
and whether you're finally flushing the output stream) -- see the FAQ
about how to post a question about code that does not work. So it's
also possible that it's a simple coding error on your part, or just a
misunderstanding.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 13 '06 #4

P: n/a

Pete Becker wrote:
Cyron wrote:
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work

Does "THIS DOES NOT WORK" mean that it doesn't compile? Some older
compilers (in particular, VC++ 6) had problems compiling operator-in a
class, so some older standard libraries don't provide it. It's supposed
to be there, though.
Thanks for the response, Pete. I am indeed using an older compiler
(Borland C++ Builder 3). I often use this compiler from the console
(as in this case) and this is the error I receive when I try to
compile:

Borland C++ 5.3 for Win32 Copyright (c) 1993, 1998 Borland
International
map.cpp:
Error map.cpp 12: Pointer to structure required on left side of -or
->* in function main()
*** 1 errors in Compile ***

Nov 13 '06 #5

P: n/a
As I understand it, in very old compilers the -operator either was
not, or could not be, overloaded. So in that case they are not identical.
Thanks for your comment, Daniel. This is the first time I recall
encountering a problem where the -wouldn't dereference a pointer to a
struct/class object. I am, however, just beginning to use templates.
Do you think the problem is related to the fact that map is a template?
Someone else also suggested the compiler's age may playing a factor so
I will check into that too.

Nov 13 '06 #6

P: n/a
Nitpick: a pointer variable does not contain anything else than a
pointer value, but the pointed to object can contain members. Thus,
it's *p that contains the member "first".
Yes you are correct. Sorry for my unclear wording. So if *p contains
a member first,
p->first should be likewise valid? Or perhaps my problem lies in my
understanding of an iterator. Currently I'm under the impression that
when I call begin() on a map, I am receving the pointer to a structure
or class which contains an element named first (provided begin() !=
end() )
I could access this member variable either by:
(*p).first OR p->first . That is, in general I thought p->x was just
shorthand for (*p).x ?

For built-in operations.
Could you elaborate on this? Do you mean built in types? How does a
map iterator differ from a "built-in operation"?
An iterator need not be a raw pointer. It can be an object that
offers
pointer operations, and then operator-and operator* are two distinct
operations that might be implemented as just displaying respectively
"huh" and "bah" on std::cout... That said, ...
Ahh, this answered the first question I had. So you are saying that
the iterator being returned is possibly not a pointer at all. In this
case I would expect (*it).first and it->first to result in errors,
since both attempt to dereference the variable, it, as if it were a
pointer? Or do you mean that both the unary * and -operators have
been re-defined so that they have nothing to do with pointers? If this
last scenario is the case, what meaning would (*it).first have?
The particular example I was working with was with printing an item
from a map:

map<string,intm ;
m.insert( make_pair( string( "test" ), false ) ) ;

map<string,int>::const_iterator it ;
for ( it = m.begin() ; it != m.end() ; it++ ) {
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work
}

... a standard library iterator is required to implement p->x to yield
the effect of (*p).x.
OK, this is what I was hoping and epecting to observe. Others
mentioned that my compiler may be too old so I will try some newer
compilers too.
Can anyone render an explanation to put my mind at ease?

Your compiler's standard library implementation seems to be broken. But
then, you haven't defined what "does not work" means, and you haven't
shown a complete program (in particular which headers you have included,
and whether you're finally flushing the output stream) -- see the FAQ
about how to post a question about code that does not work. So it's
also possible that it's a simple coding error on your part, or just a
misunderstanding.
Yes, forgive me for the lack of information and the ambiguity regarding
the program details. Below is the exact program I am using. The
following contents are stored in map.cpp:
#include <string>
#include <map>
#include <iostream>

using namespace std ;
int main() {
map<string,inttest ;
test.insert( make_pair( string( "test" ), 5 ) ) ;
map<string, int>::iterator it;

for ( it = test.begin() ; it != test.end() ; ++it ) {
std::cout << it->first ; // Statement in question
}
return( 0 ) ;
}
If the line marked as "Statement in question" is as shown above an
attempt to compile (bcc32 map.cpp) results in:

Borland C++ 5.3 for Win32 Copyright (c) 1993, 1998 Borland
International
map.cpp:
Error map.cpp 12: Pointer to structure required on left side of -or
->* in function main()
*** 1 errors in Compile ***

At first glance I would normally think this error message indicates
that "it" is not a pointer. I looked around online to find a solution
and saw someone using *it so tried it instead of the -and voila! it
worked. That is, if i replace the "Statement in question" in the above
program with:

std::cout << (*it).first ; // Statement in question

The program compiles with no errors and functions as expected.

This led me to believe that "it" was indeed a pointer, but for some
reason * and not -were working with it.

Nov 13 '06 #7

P: n/a
* Cyron:
>Nitpick: a pointer variable does not contain anything else than a
pointer value, but the pointed to object can contain members. Thus,
it's *p that contains the member "first".

Yes you are correct. Sorry for my unclear wording. So if *p contains
a member first,
p->first should be likewise valid? Or perhaps my problem lies in my
understanding of an iterator. Currently I'm under the impression that
when I call begin() on a map, I am receving the pointer to a structure
or class which contains an element named first (provided begin() !=
end() )
Nope, it /can't/ be a pointer because a map cannot be a contigous
structure (because of performance requirements of its operations), and
you're incrementing the iterator to go from item to item.

>>I could access this member variable either by:
(*p).first OR p->first . That is, in general I thought p->x was just
shorthand for (*p).x ?
For built-in operations.

Could you elaborate on this? Do you mean built in types? How does a
map iterator differ from a "built-in operation"?
Given (off the cuff, not tested)

struct Value
{
int x;
};

Value const v = { 12345 };

struct Accessor
{
Value const* operator->() const { return &v; }
Value const& operator*() const { return v; }
};

int main()
{
Accessor const a;

std::cout << (*a).x << std::endl;
std::cout << a->x << std::endl;
}

the first output statement is (conceptually) translated to

Value const& _r = a.operator*();
std::cout _r.x << std::endl;

and the second output statement is translated to

Value const* _p = a.operator->();
std::cout << _p->x << std::endl;

which if the Value class offers its own operator-will in turn result
in a call to /that/ operator->, and so on, but since the Value class
doesn't, the -is here the built-in pointer operation, this ends up as

Value const* _p = a.operator->();
std::cout << (*_p).x << std::endl;

An iterator need not be a raw pointer. It can be an object that
offers
>pointer operations, and then operator-and operator* are two distinct
operations that might be implemented as just displaying respectively
"huh" and "bah" on std::cout... That said, ...

Ahh, this answered the first question I had. So you are saying that
the iterator being returned is possibly not a pointer at all. In this
case I would expect (*it).first and it->first to result in errors,
since both attempt to dereference the variable, it, as if it were a
pointer? Or do you mean that both the unary * and -operators have
been re-defined so that they have nothing to do with pointers?
Yes, essentially.

If this
last scenario is the case, what meaning would (*it).first have?
'*it' produces a C++ reference, an alias for some object.

>> The particular example I was working with was with printing an item
from a map:

map<string,intm ;
m.insert( make_pair( string( "test" ), false ) ) ;

map<string,int>::const_iterator it ;
for ( it = m.begin() ; it != m.end() ; it++ ) {
cout << it->first ; // THIS DOES NOT WORK
cout << (*it).first ; // This does work
}
... a standard library iterator is required to implement p->x to yield
the effect of (*p).x.

OK, this is what I was hoping and epecting to observe. Others
mentioned that my compiler may be too old so I will try some newer
compilers too.
Good idea.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 13 '06 #8

P: n/a
Cyron:
That is, in general I thought p->x was just shorthand for (*p).x ?

And you were correct to think that, because it is.

The particular example I was working with was with printing an item
from a map:

map<string,intm ;
m.insert( make_pair( string( "test" ), false ) ) ;

You do realise that that invocation of "make_pair" will yield a pair
<string,booland not a pair<string,int>, right?

Can anyone render an explanation to put my mind at ease?

As others have pointed out, you're using a K++ compiler. Get a C++ one.

--

Frederick Gotham
Nov 13 '06 #9

P: n/a
If this
last scenario is the case, what meaning would (*it).first have?

'*it' produces a C++ reference, an alias for some object.
Thank You for your explanations and example, Alf. I believe I now have
an understanding of the situation.

Mike

Nov 13 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.