REFERENCES REVEALED

J

Jorge Rivera

Can anyone here suggest any reason at all why the following expression would
be false?:


sizeof(BankAccountInfoPointers) == sizeof(BankAccountInfoReferences)

Because sizeof(---Pointers) has to be the size of a number (16,32,64
bits). sizeof(---References) could well result in giving you the size
of the object it refers to.

This isn't an ignorant rhetorical question, I'm genuinely interested in a
possible reason, other than "'cause the Standard doesn't says it has to be".
But that is the reason you have to weight the most. If the standard
does not guarantee this, and there is a clever way of implementing
reference behavior that is not based on pointers, all your underlying
assumptions will be lost.

If yu had a car before the 80s, you would have probably assumed that the
only way to pump gas is through a carburator. Nowadays, this is rarely
true. What I mean is, the fact that references are implemented as
pointers today does not guarantee that it always will, and you MUST
realize this.

Stop arguing. What's the point?

Jorge L.
 
M

Mabden

Jorge Rivera said:
Because sizeof(---Pointers) has to be the size of a number (16,32,64
bits). sizeof(---References) could well result in giving you the size
of the object it refers to.


But that is the reason you have to weight the most. If the standard
does not guarantee this, and there is a clever way of implementing
reference behavior that is not based on pointers, all your underlying
assumptions will be lost.

If yu had a car before the 80s, you would have probably assumed that the
only way to pump gas is through a carburator. Nowadays, this is rarely
true. What I mean is, the fact that references are implemented as
pointers today does not guarantee that it always will, and you MUST
realize this.

Ah. So, altho they probably ARE const pointer right now, they are an IDEA
and should not be counted on in the future; much like ints always being 16
bits (remember back when...).
 
K

Karl Heinz Buchegger

Mabden said:
Ah. So, altho they probably ARE const pointer right now,

They CAN be.
But the ARE NOT.

A reference may exist in the symbol table of your compiler
only.
When your compiler encounters this piece of code:

int main()
{
int i;
int& j;

it creates 2 entries in its symbol table, one for i, one for j.
The point is: The compiler marks j as beeing a reference to i.
Now when the compiler compiles

j = 5;

It looks up j in its internal symabol table and figures out that
j is an alias for i. So the compiler modifies the statement
to read

i = 5;

and compiles that instead.

In the final exacutable, j doesn't even show up and this has nothing
to do with some optimizations. It's just a consequence of: a reference
is another name to an already existing object.
 
K

Karl Heinz Buchegger

JKop said:
Karl Heinz Buchegger posted:


struct Jeep
{
std::Vector& a;
std::Vector& b;
};

Then explain the above. If it's just another name for a variable, then what
the hell are a and b ?
References.


Pointers is what they are, and on a 32-Bit Memory Model platform, sizeof
(Jeep) will be 64 Bits, which proves my point.

Which proves exactly nothing.
An example is not a proof.
 
O

Old Wolf

JKop said:
I finally understand reference variables perfectly!! It's the way that they
were described to me that had me all confused. The books I've learned from
have never just stated plainly:
A reference variable is just a pointer variable.

I should hope not, since they would be wrong.
Look man, several people with many years of practical C++ experience
have told you that you are wrong. Maybe you should start listening to them?
struct Jeep
{
std::Vector& a;
std::Vector& b;
};

int main(void)
{
Vector j;
Vector k;

Jeep jeep = {j, k};
}
Then explain the above. If it's just another name for a variable, then what
the hell are a and b ?

'a' and 'b' are other names for variables, as you say.

If you consider this slightly modified (and compilable) example:

struct Jeep
{
std::vector<int> &a;
Jeep(std::vector &a_): a(a_) {}
};

int main()
{
std::vector<int> v;
Jeep j(v);

j.a.push_back(10);
v.push_back(12);
}

"j.a" and "v" mean exactly the same thing. If you picture the memory
location of the vector in your mind, think of it as having two labels
"j.a" and "v". These two terms are completely interchangeable, in
any expression. If you think about it for a moment, you would realise
that the same is not true of pointers.
Pointers is what they are, and on a 32-Bit Memory Model platform, sizeof
(Jeep) will be 64 Bits, which proves my point.

It would be difficult for the compiler to maintain a list of which
label refers to which object, by any means other than storing the
address of that object with that label. Implementations use addresses
internally when remembering what references are bound to.

Implementation details do not "prove your point". (On one of my
systems, sizeof(int) is 2. Does this prove that ints have 16 bits?)

It's good that you have something in mind that gives you a better
handle on references. But you should bear in mind that this is
an imperfect description, and you will become confused in future
when you encounter problems with it. For example, as you pointed
out yourself,

int Monkey() { return 42; }
int main()
{
int const &k = Monkey();
std::cout << k << std::endl;
return 0;
}

How would you write that with const pointers? What is &k?

It's like the "dump-truck" analogy for electricity (each electron is
loaded up with power, and as it passes through the bulb, it dumps all
its power so the bulb glows). Seems like a good idea, but is actually
totally wrong, and worse than useless.
 
J

JKop

int Monkey() { return 42; }
int main()
{
int const &k = Monkey();
std::cout << k << std::endl;
return 0;
}


You're accessing unallocated memory there - the temporary no longer
exists.


-JKop
 
J

JKop

John Harrison posted:

From the practical point of view there is the fact that a const
reference can bind to a temporary, something a pointer cannot do.


int Monkey(void) { return 42; }


void Parrot(int* pBeak)
{

std:: cout << *pBeak;

}


int main(void)
{

int* k;


Parrot( &( *k = Monkey() ) );


system("PAUSE");

}



I love it!



If anyone could post something from the Standard regarding the lifetime of
temporaries, I'd appreciate it. As far as I know, the above is valid, ie.
DEFINED BEHAVIOUR!


-JKop
 
R

Rob Williscroft

JKop wrote in in comp.lang.c++:
John Harrison posted:




int Monkey(void) { return 42; }


void Parrot(int* pBeak)
{

std:: cout << *pBeak;

}


int main(void)
{

int* k;

k points where ?
Parrot( &( *k = Monkey() ) );

You've just writen (*k =) the value 42 to some random location.

This is Undefined Behavior.
system("PAUSE");

}



I love it!

Whats to love ?
If anyone could post something from the Standard regarding the
http://www.techstreet.com/cgi-bin/detail?product_id=1143945

lifetime of temporaries, I'd appreciate it. As far as I know, the
above is valid, ie. DEFINED BEHAVIOUR!

No its UB.


Rob.
 
K

Karl Heinz Buchegger

JKop said:
You're accessing unallocated memory there - the temporary no longer
exists.

He is not.
JKop you have posted since a few days and some of your posts
are really good. But your knowledge is weak. There are a few
regulars in this group you should listen to. You can only learn
from them.

As why the above is not accessing unallocated memory:
When a temporary is bound to a reference, the lifetime
of the temporary is also bound to the lifetime of the
reference. The temporary lives as long as the reference
lives.
 
K

Karl Heinz Buchegger

JKop said:
John Harrison posted:


int Monkey(void) { return 42; }

void Parrot(int* pBeak)
{

std:: cout << *pBeak;

}

int main(void)
{

int* k;


Parrot( &( *k = Monkey() ) );


system("PAUSE");

}

I love it!

If anyone could post something from the Standard regarding the lifetime of
temporaries, I'd appreciate it. As far as I know, the above is valid, ie.
DEFINED BEHAVIOUR!

Take more care!
The above is undefined behaviour. Where does k point to when you
dereference it. Just because it compiles and runs at your system
doesn't mean it is correct.
 
M

Mabden

Karl Heinz Buchegger said:
Take more care!
The above is undefined behaviour. Where does k point to when you
dereference it. Just because it compiles and runs at your system
doesn't mean it is correct.


Sorry for the quote-to-comment ratio, but WTF?!!

Can you guys figure it out and post the actual truth about how this works? I
don't know enough to figure it out and you are getting less helpful as you
post snipettes. Somebody please summarize the argument and explain how
pointers (or const pointer) and references differ in the Real World (tm).
 
K

Karl Heinz Buchegger

Mabden said:
[snip]

Can you guys figure it out and post the actual truth about how this works?

You mean the above?
That's undefined behaviour.
k is derefenced without having given a location to point to.
I
don't know enough to figure it out and you are getting less helpful as you
post snipettes. Somebody please summarize the argument and explain how
pointers (or const pointer) and references differ in the Real World (tm).

????
There have already been given some good answers.
Both are distinct concepts:
A pointer is a variable which holds a memory address.
A reference is another name to an existing object

Sometimes a compiler uses a pointer internally to implement
reference semantics. Sometimes not. The point with references
is, that for you as the programmer there is no legal way to
differentiate between the references and the thing it refers
to. For you, the programmer, they are the same thing.

int main()
{
int i;
int& j = i;
}

j and i are indistinguishable. They are just 2 names for the
same memory location where an int is stored. How the compiler
does this magic is unimportant and completely transparent to you.

A pointer variable is a variable on its own: it has a value
and it has a location in memory where it resides.
 
J

JKop

Karl Heinz Buchegger posted:
Take more care!
The above is undefined behaviour. Where does k point to when you
dereference it. Just because it compiles and runs at your system
doesn't mean it is correct.


I'm not convinced that what I've done in the above is undefined behaviour.

Take the following function:


const unsigned long int* Tranquil(const unsigned long int& ostrich)
{
const unsigned long int* const pOstrich = &ostrich;

return pOstrich;
}


That's defined behaviour... Yes?


int main(void)
{
const unsigned long int* pFlamingo = Tranquil(55982UL);
}


And the above is also defined behaviour... Yes?


So what's wrong with my original example?!


-JKop
 
L

Luther Baker

JKop said:
Karl Heinz Buchegger posted:

If you don't initialize k, where does k reside and what is the value at
that location?

For sake of argument, let's assume it resides at 0x80808080.

Ok, now, how about the value for k? Well, k is 4 bytes long and we know
it starts at 0x80808080 ... so, its going to be random, right? Lets just
say the 4 bytes starting from address 0x80808080 are 0xaabbccdd. Again,
what I'm referring to here is the random bit pattern that exists at the
address in memory where k resides.

Now, assume this works as you think, where does the value '42' get written?

assuming k resides at memory address 0x80808080
and the value of k = 0xaabbccdd

then ----> the operating system jumps to address
0xaabbccdd and writes the value 0x0000002a.

Notice, the location where k resides hasn't changed ... and the actual
bit pattern at that location didn't change. Your code will change the
bits at the random address that k is holding or pointing to.

So, we agree that the value of k is random right? What if the bit
pattern at address 0x80808080 is 0x00000000 or NULL. We don't know? It
could be. There's no of any value.

So try this:

int* k = 0;

In this case, *k* is validly declared - and so, let us assume it still
resides at address 0x80808080. But this time, we assigned a value to the
4 bytes. The 4 bytes from 0x80808080 ~ 0x80808084 will be 0x00000000.

Now try:

*k = 5;

What do you get? Sure, it compiles fine. It won't run. Why not? Well, it
just so happens that NULL or 0x0 is an address that cannot be written to.

So, in your example, if the value of k at address 0x80808080 equals NULL
or 0x00000000, what will happen when you try to write the value 42 to *k.

Do you understand what happens when you dereference a pointer? The value
is not written to the location the pointer exists in memory - it is
written to the place the pointer _points-to_ in memory. In this example,
we are trying to write the value '42' to the address location 0x00000000
and that will break.

Take this example and extend it. Imagine a memory address too large.
Imagine a memory address already in use in the system. Remember, the
bits at k are going to be random ...

Your example as its written, isn't really about temporaries. Its about
dangling pointers.

This question actually goes back to when you didn't agree with Julie
that dangling pointers are _bad_. When one dereferences a dangling
pointer, its possible they may point to memory that the compiler is
happily using for other things. Writing, reading, etc. If you try to
access memory with a dangling pointer, you're not going to necessarily
break anything - but you can't depend on anything being there ... since
the operating system is tracking and using memory like a mad man.

And if you write to a dangling pointer - you might be overwriting
something the OS just put there. Or, you might be writing to a blank
area - or you might be writing to NULL (which would throw an exception).

Maybe _bad_ isn't the word, but the resulting behavior is unpredictable
if you tried to write or read from a dangling pointer -- and therefore,
it is undefined.

Hth,

-Luther

(If all this pointer talk is confusing, try reading K&R or some other C
text).
 
J

JKop

Luther Baker posted:
If you don't initialize k, where does k reside and what is the value at
that location?


Opps!!

Rookie mistake! I didn't look close enough at my code.

Believe me, I know exactly what my original code is doing:

int *pHello;

*pHello = 5;


I was just focusing too much on trying to get the address of the return
value from the function, and I was wasn't watching the road!

I know realize that you simply just can't get the address of the return
value from a function!


-JKop
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top