reading a declaration

A

Alan

// C Pointer
int y = 0;
int* ptr = &y;

Reads as "ptr is an integer pointer that points to (takes the
address of) integer y".

// C++ Reference
int x = 0;
int& ref = x;

What does this read as?

TIA, Alan
 
R

Rolf Magnus

Alan said:
// C Pointer
int y = 0;
int* ptr = &y;

Reads as "ptr is an integer pointer that points to (takes the
address of) integer y".
Yes.


// C++ Reference
int x = 0;
int& ref = x;

What does this read as?

"ref is a reference to int that refers to (is an alias name for) x".
 
R

Richard Herring

Alan said:
// C Pointer
int y = 0;
int* ptr = &y;

Reads as "ptr is an integer pointer that points to (takes the
address of) integer y".

// C++ Reference
int x = 0;
int& ref = x;

What does this read as?

"ref is a reference to integer that is bound to integer variable x."
 
A

Alan

Rolf Magnus said:
"ref is a reference to int that refers to (is an alias name for) x".

I know what you're saying but "refers to" (or "bound to" as
Richard Herring writes) doesn't really tell the reader what
the relationship is, imo. References are really compiler
undecorated pointers:

// C++ Reference
int x = 0;
int& ref = x;

// C Pointer
int y = 0;
int* ptr = &y;

....

// Reference
cout << "x = " << x << ", ref = " << ref << endl; // x = 0, ref = 0
a++;
cout << "x = " << x << ", ref = " << ref << endl; // x = 1, ref = 1

// Pointer
cout << "y = " << y << ", *ptr = " << *ptr << endl; // y = 0, *ptr = 0
(*b)++;
cout << "y = " << y << ", *ptr = " << *ptr << endl; // y = 1, *ptr = 1

"a++" is far more preferable to "(*b)++" but I question the choice of terminology in declaring a reference.

'&' denotes 'address of' (for backward compatibility with C) but in
"int& ref = x" or the syntactical equivalent "int &ref = x" , it doesn't
make any sense if it is read in the context of 'address of'.

imo, "int ref = &x" makes more sense.

I wonder why Bjarne didn't just fix the problems with pointers
(hanging pointers, pointers that don't point to anything, void*
pointers, etc) and then use the compiler to undecorate them ;-)

Alan
 
R

Richard Herring

Alan said:
I know what you're saying but "refers to" (or "bound to" as
Richard Herring writes) doesn't really tell the reader what
the relationship is, imo. References are really compiler
undecorated pointers:

Except when there's no need for a pointer, as in this case.
// C++ Reference
int x = 0;
int& ref = x;

The compiler is quite likely to emit identical code, not involving any
pointers at all, for "do <something> with x" and "do <something> with
ref" said:
// C Pointer
int y = 0;
int* ptr = &y;

...

// Reference
cout << "x = " << x << ", ref = " << ref << endl; // x = 0, ref = 0
a++;
cout << "x = " << x << ", ref = " << ref << endl; // x = 1, ref = 1

// Pointer
cout << "y = " << y << ", *ptr = " << *ptr << endl; // y = 0, *ptr = 0
(*b)++;
cout << "y = " << y << ", *ptr = " << *ptr << endl; // y = 1, *ptr = 1

"a++" is far more preferable to "(*b)++" but I question the choice of
terminology in declaring a reference.

'&' denotes 'address of' (for backward compatibility with C)

Even in C, you could equally well say it denotes "pointer to". It's just
the inverse of *. People approaching C++ from a Java background probably
have the same objections to pointers.
but in
"int& ref = x" or the syntactical equivalent "int &ref = x" , it doesn't
make any sense if it is read in the context of 'address of'.

So don't say "address of", say "alias for" ;-)
imo, "int ref = &x" makes more sense.

Not in the context of the C and C++ reading-from-inside-to-out,
declaration-matches-use rules.
I wonder why Bjarne didn't just fix the problems with pointers
(hanging pointers, pointers that don't point to anything, void*
pointers, etc) and then use the compiler to undecorate them ;-)
That's called Java. Or maybe C#.
 
R

Rolf Magnus

Richard said:
The compiler is quite likely to emit identical code, not involving any
pointers at all, for "do <something> with x" and "do <something> with
ref", for any or all instances of <something>.

The same would be true for the int* ptr, too. I don't see any case where a
compiler would have more potential for optimization with a reference than
with a (constant or verifyably unchanged) pointer.
 
M

Mike Wahler

Alan said:
// C Pointer
int y = 0;
int* ptr = &y;

Reads as "ptr is an integer pointer that points to (takes the
address of) integer y".

// C++ Reference
int x = 0;
int& ref = x;

What does this read as?

'ref' is a reference to the object 'x'. IOW 'ref'
is an alternate name (a.k.a an 'alias') for 'x'.
'ref' is not an object.

-Mike
 
M

Mike Wahler

Alan said:
I know what you're saying but "refers to" (or "bound to" as
Richard Herring writes) doesn't really tell the reader what
the relationship is, imo. References are really compiler
undecorated pointers:

No. A reference is *not* a pointer. (an implementation might
indeed internally implement references via pointers, but the fact
remains that from a language perspective, a reference is not a
pointer. Note that a pointer is an object, a reference is not.
// C++ Reference
int x = 0;
int& ref = x;

// C Pointer
int y = 0;
int* ptr = &y;

...

// Reference
cout << "x = " << x << ", ref = " << ref << endl; // x = 0, ref = 0
a++;
cout << "x = " << x << ", ref = " << ref << endl; // x = 1, ref = 1

// Pointer
cout << "y = " << y << ", *ptr = " << *ptr << endl; // y = 0, *ptr = 0
(*b)++;
cout << "y = " << y << ", *ptr = " << *ptr << endl; // y = 1, *ptr = 1

"a++" is far more preferable to "(*b)++" but I question the choice of
terminology in declaring a reference.
'&' denotes 'address of' (for backward compatibility with C) but in
"int& ref = x" or the syntactical equivalent "int &ref = x" , it doesn't
make any sense if it is read in the context of 'address of'.

Of course not, it's an 'overloaded' use of the & operator. Even C
'overloads' some operators (their meaning depends upon context).
imo, "int ref = &x" makes more sense.

Not to me. '&x' already has the well-defined meaning of
'address of'. A reference is not an address, nor is it
a pointer.
I wonder why Bjarne didn't just fix the problems with pointers
(hanging pointers, pointers that don't point to anything, void*
pointers, etc) and then use the compiler to undecorate them ;-)

I have no idea what you mean by 'decorate' or 'undecorate'.

-Mike
 
D

David White

Alan said:
'&' denotes 'address of' (for backward compatibility with C) but in
"int& ref = x" or the syntactical equivalent "int &ref = x" , it doesn't
make any sense if it is read in the context of 'address of'.

It's not supposed to. '&', the address-of operator, and '&', the reference
declaration, are completely unrelated. They just happen to use the same
symbol.
imo, "int ref = &x" makes more sense.

It doesn't make any sense to me. 'int ref' defines a plain int and '&' is
the address-of operator.
I wonder why Bjarne didn't just fix the problems with pointers
(hanging pointers, pointers that don't point to anything, void*
pointers, etc) and then use the compiler to undecorate them ;-)

And how do you suggest he should have "fixed" them?

DW
 
A

Alan

[snip]

To prove that a reference is really a (fancy) pointer
I have provided part of the ASM listing for the
following C++ program (test5.cpp).

Because some of the std library calls and arguments are
very long and add nothing to the discussion, I have
replaced them with "xxxx" but preserved the added comments.

{ my comments in braces }

1 #include <iostream>
2 using namespace std;

3 int x = 0;
4 int& a = x;

5 int main() {
6 cout << "x = " << x << ", a = " << a << endl;
7 a++;
8 cout << "x = " << x << ", a = " << a << endl;
9 return 0;
10 }


{ assembly listing }
PUBLIC ?x@@3HA ; x
PUBLIC ?a@@3AAHA ; a

_BSS SEGMENT
?x@@3HA DD 01H DUP (?) ; x
?a@@3AAHA DD 01H DUP (?) ; a
_BSS ENDS

; File test5.cpp
; Line 4 { int& a = x; }
push ebp
mov ebp, esp
mov DWORD PTR ?a@@3AAHA, OFFSET FLAT:?x@@3HA ; a, x
pop ebp
ret 0
{ Moves the address (or offset) of 'x' into 'a' i.e. 'a' points to 'x' }

_main PROC NEAR
; Line 5
push ebp
mov ebp, esp

; Line 6 { cout << "x = " << x << ", a = " << a << endl; }
push OFFSET FLAT:xxxx ; std::endl
mov eax, DWORD PTR ?a@@3AAHA ; a
mov ecx, DWORD PTR [eax] { get what 'a' points to }
push ecx { push value on stack }
push OFFSET FLAT:$SG7505
mov edx, DWORD PTR ?x@@3HA ; x
push edx
push OFFSET FLAT:$SG7506
push OFFSET FLAT:xxxx ; std::cout
call xxxx ; std::eek:perator<<
add esp, 8
mov ecx, eax
call xxxx ; std::basic_ostream<char,std::char_traits<char> >::eek:perator<<
push eax
call xxxx ; std::eek:perator<<
add esp, 8
mov ecx, eax
call xxxx ; std::basic_ostream<char,std::char_traits<char> >::eek:perator<<
mov ecx, eax
call xxxx ; std::basic_ostream<char,std::char_traits<char> >::eek:perator<<

; Line 7 { a++; }
mov eax, DWORD PTR ?a@@3AAHA ; a
mov ecx, DWORD PTR [eax] { get the value that 'a' points to }
add ecx, 1 { increment the value }
mov edx, DWORD PTR ?a@@3AAHA ; a
mov DWORD PTR [edx], ecx { write the new value back }

; Line 8 { cout << "x = " << x << ", a = " << a << endl; }
push OFFSET FLAT:xxxx ; std::endl
mov eax, DWORD PTR ?a@@3AAHA ; a
mov ecx, DWORD PTR [eax]
push ecx
push OFFSET FLAT:$SG7649
mov edx, DWORD PTR ?x@@3HA ; x
push edx
push OFFSET FLAT:$SG7650
push OFFSET FLAT:xxxx ; std::cout
call xxxx ; std::eek:perator<<
add esp, 8
mov ecx, eax
call xxxx ; std::basic_ostream<char,std::char_traits<char> >::eek:perator<<
push eax
call xxxx ; std::eek:perator<<
add esp, 8
mov ecx, eax
call xxxx ; std::basic_ostream<char,std::char_traits<char> >::eek:perator<<
mov ecx, eax
call xxxx ; std::basic_ostream<char,std::char_traits<char> >::eek:perator<<

; Line 9 { return 0; }
xor eax, eax

; Line 10
pop ebp
ret 0
_main ENDP
 
D

David White

Alan said:
[snip]

To prove that a reference is really a (fancy) pointer
I have provided part of the ASM listing for the
following C++ program (test5.cpp).

Because some of the std library calls and arguments are
very long and add nothing to the discussion, I have
replaced them with "xxxx" but preserved the added comments.

{ my comments in braces }

1 #include <iostream>
2 using namespace std;

3 int x = 0;
4 int& a = x;

5 int main() {
6 cout << "x = " << x << ", a = " << a << endl;
7 a++;
8 cout << "x = " << x << ", a = " << a << endl;
9 return 0;
10 }


{ assembly listing }
PUBLIC ?x@@3HA ; x
PUBLIC ?a@@3AAHA ; a

_BSS SEGMENT
?x@@3HA DD 01H DUP (?) ; x
?a@@3AAHA DD 01H DUP (?) ; a
_BSS ENDS

; File test5.cpp
; Line 4 { int& a = x; }
push ebp

[snip]

The assembly listing is irrelevant, and so are your comments on it. A
compiler can implement references however it likes. Using an address to the
referred-to object is obviously a natural choice for a compiler to make on
the machines with which most of us are familiar. We already knew that.
However, as far as the C++ language is concerned, a reference is not a
pointer. It is an alias for an object.

DW
 
G

Gary Labowitz

Alan said:
[snip]

To prove that a reference is really a (fancy) pointer
I have provided part of the ASM listing for the
following C++ program (test5.cpp).
<<large snip>>

You can't use an implementation as an explanation of a standard. It's the
other way 'round.
Anyway, what's so difficult about reading
int &ref = x;
as "ref is another identifier for the int already declared with identifier
x?"
The compiler nods, and says: okay whenever you use the identifier "ref" I'll
use the value in "x." How I do it is none of your business.
A really smart optimizer would just emit the same code for the following two
assignments:
ref = 10;
x = 10;
No need to use a pointer to dereference the address of x.
But that is up to the implementation. It could instead do all sorts of
lookups to find the address of the value in memory.

My point? The standard says what you can do as a programmer. The compiler is
just a way to get your code into machine language.
 
D

Dave O'Hearn

Alan said:
To prove that a reference is really a (fancy) pointer
I have provided part of the ASM listing for the
following C++ program (test5.cpp).

Because some of the std library calls and arguments are
very long and add nothing to the discussion, I have
replaced them with "xxxx" but preserved the added comments.

I don't think it's entirely wrong to view references as a form of
pointers, but you need to be a bit clearer than just saying it's a
fancy pointer.

I typically consider a reference to be a pointer that is implicitly
dereferenced in all operations except initialization. This also
implicitly makes all references const (though not TO const), since
there is no way to access the pointer to reassign it; it is always
implicitly dereferenced. You can use the & operator to get the address,
but it produces an rvalue, the same way &(*p) produces an rvalue.

This is not how the Standard describes references, but I believe it is
isomorphic to it, so there is no difference. If someone knows of one,
I'd be interested in hearing it. But note that "the reference may have
no runtime representation" does not count. That is a red herring, as it
is equally true of pointers, and everything else.
 
M

Mike Wahler

Alan said:
[snip]

To prove that a reference is really a (fancy) pointer
I have provided part of the ASM listing for the
following C++ program (test5.cpp).

That is no proof at all. All it proves is how a
particular compiler implements a reference. That
does not change the fact that a reference is not a
pointer. If it were a pointer, after initializing
it, you could make it point somewhere else. But you
cannot.

int i = 42;
int j = 99;
int& r = i

r = j; /* assigns the value of 'i' to 'j',
does *not* cause 'r' to refer to 'j' */

cout << i; /* prints 99, not 42 */

-Mike
 
M

Mike Wahler

Dave O'Hearn said:
I don't think it's entirely wrong to view references as a form of
pointers,

It is wrong. A reference is *not* a pointer. Period.
but you need to be a bit clearer than just saying it's a
fancy pointer.

Saying it is *any* kind of pointer is incorrect.
I typically consider a reference to be a pointer that is implicitly
dereferenced in all operations except initialization.

That is not the case.
This also
implicitly makes all references const (though not TO const), since
there is no way to access the pointer to reassign it;

There is *no* pointer.
it is always
implicitly dereferenced.

Only a pointer (or an iterator) can be dereferenced. A reference
is *not* a pointer.
You can use the & operator to get the address,

That will yield the address of the object to which the
reference refers. A reference is not an object, it
has no address.
but it produces an rvalue, the same way &(*p) produces an rvalue.

This is not how the Standard describes references,

Of course not, because it's utterly wrong.
but I believe it is
isomorphic to it, so there is no difference.

There's a huge difference.
If someone knows of one,
I'd be interested in hearing it.

A reference is not a pointer. It's not an object, it has no address.
The same is not true of a pointer.
But note that "the reference may have
no runtime representation" does not count. That is a red herring,


Not at all.
as it
is equally true of pointers, and everything else.


No it's not. A pointer is an object, and occupies storage.
A reference does not.

-Mike
 
R

Rolf Magnus

Mike said:
It is wrong. A reference is *not* a pointer. Period.

However, it works similar to a constant pointer (they can e.g. be used for
polymorphism the same way as pointers can). The semantics are of course
very different though.
That is not the case.

It isn't so different from that.
No it's not. A pointer is an object, and occupies storage.
A reference does not.

If a reference does not occupy storage, explain this:

#include <iostream>

struct A
{
int x;
};

struct B
{
B(int& i) : y(i) {}

int x;
int& y;
};

int main()
{
std::cout << "A: " << sizeof(A) << " B: " << sizeof(B) << '\n';
}

Output on my system:

A: 4 B: 8
 
D

Dave O'Hearn

Mike said:
It is wrong. A reference is *not* a pointer. Period.

I didn't say it was. Note the qualifiers "not entirely wrong" and
"view".
Saying it is *any* kind of pointer is incorrect.

I didn't say it was. But try this: "A reference has identical syntax
and semantics to a pointer that is implicitly dereferenced, in all
operations except initialization." I believe this description is
flawless.

There are others who occasionally explain references as being related
to pointers in some way:

"The obvious implementation of a reference is as a (constant) pointer
that is dereferenced each time it is used. It doesn't do much harm
thinking about references that way, as long as one remembers that a
reference isn't an object that can be manipulated the way a pointer
is:" [TC++PL, page 98]

Of course, Stroustrup's analogy is just illustration. I am claiming
mine is perfect. So it is more of an issue if mine has exceptions.
Still, I asked for exceptions to be pointed out, and if there are any,
they can be listed as special cases. If there are too many special
cases, the whole of it can be used as an example of how thinking of
references as "like pointers" leads to pitfalls. But as of yet, the
only exception I know is initialization. Initialization includes
passing references as arguments.
[...]
This is not how the Standard describes references,

Of course not, because it's utterly wrong.

How would the C++ language be different, if references were defined the
way I said, instead of how it is done in the standard? You tried to
point out a way below, but the as-if rule makes it irrelevant.
A reference is not a pointer. It's not an object, it has no
address. The same is not true of a pointer.


No it's not. A pointer is an object, and occupies storage.
A reference does not.

Doesn't count, since it is purely lingustic. In the standard
explanation it is a primary that the reference occupies no storage. In
my analogy, it is a secondary consequence; the storage can never be
accessed. By the as-if rule, this is equivalent to it having no
storage.

I am looking for a way in which my above explanation of references
would result in wrong code, or code with a different meaning, than the
standard-ise explanation of references. C++ is not a standards
document; it is the language defined by that document. There are often
multiple ways of defining the same construct. The same is true of
languages.

Also, this is not the only to think about references. The standard's
way of doing it is fine too. And I sometimes think of references as
follows,

- objects have value syntax and value semantics
- pointers have reference syntax and reference semantics
- (pointers are objects, and they also have value operations)
- references have value syntax but reference semantics

I think this view is most helpful when deciding whether to pass an
argument by pointer with its address, or by reference.
 
G

Gary Labowitz

I think this view is most helpful when deciding whether to pass an
argument by pointer with its address, or by reference.

You got me thinking; isn't a reference more like a #define that has scope?
What I mean is: #define ref x
would do what int &ref = x;
does EXCEPT with define there is no scope or type checking. In other words,
whenever the compiler sees ref, it uses x.
If so, couldn't a compiler implement the references by precompiling them
with the substitution, adding #defines to set and unset the variable and
then
compile as normally? This would be a lot of overhead, of course, but would
it give the same result?
 
K

Karl Heinz Buchegger

Gary said:
You got me thinking; isn't a reference more like a #define that has scope?
What I mean is: #define ref x
would do what int &ref = x;
does EXCEPT with define there is no scope or type checking. In other words,
whenever the compiler sees ref, it uses x.

If the compiler sees what the reference refers to, yes there is some
similarity.
Actually I would guess this is what most compilers will do:
In the compiler internal table of variables mark each variable if it is a
reference. If it is, then this table also contains the name of the object
the reference stands for.

Whenever the compiler encounters a variable somewhere, it looks up that table
to see if it is a reference. If it is, the compiler checks if the object the
reference stands for is known to it. If it is, the compiler substitutes the
reference variable with the object the reference stands for and continues with
that instead of the reference.
If so, couldn't a compiler implement the references by precompiling them
with the substitution, adding #defines to set and unset the variable and
then
compile as normally? This would be a lot of overhead, of course, but would
it give the same result?

ignoring all problems with #define right now, I think it would work in principle,
iff the compiler knows what the reference stands for. But it doesn't in all
cases :)

Another reason why it is not done this way is, that the preprocessor should not know
to much about actual C++ syntax and the reference information can be stored
easily in a compiler internal table which is present anyway.
 
M

msalters

Gary said:
You got me thinking; isn't a reference more like a #define that has scope?
What I mean is: #define ref x
would do what int &ref = x;
does EXCEPT with define there is no scope or type checking. In other words,
whenever the compiler sees ref, it uses x.

Except, of course, that there are many cases in which the compiler
doesn't see what it has to use. E.g.

void print( int const& x ) { // x refers to?
std::cout << x;
}

void foo() {
int i = 0;
print( i ); the x in print() will refer to i
int j = 1;
print( j ); the x in print() will refer to j
print( 3 ); the x in print() will refer to some constant 3
print( 3+1 ); the x in print() will refer to some temporary 4
}

Regards,
Michiel Salters
 

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

Forum statistics

Threads
474,189
Messages
2,571,015
Members
47,616
Latest member
gijoji4272

Latest Threads

Top