Pointer Dereferencing

C

Cyron

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,int> m ;
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
 
P

Pete Becker

Cyron said:
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.
 
D

Daniel T.

"Cyron said:
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,int> m ;
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.
 
A

Alf P. Steinbach

* 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,int> m ;
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.
 
C

Cyron

Pete said:
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 ***
 
C

Cyron

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.
 
C

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() )
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?
... 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.
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,int> test ;
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.
 
A

Alf P. Steinbach

* Cyron:
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.

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;

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.

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.
 
F

Frederick Gotham

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,int> m ;
m.insert( make_pair( string( "test" ), false ) ) ;


You do realise that that invocation of "make_pair" will yield a pair
right? said:
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.
 
C

Cyron

If this
'*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
 

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,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top