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

REFERENCES REVEALED

P: n/a

I understand variables/objects and pointer variables perfectly:

int X = 5;

int* pX = &X;

*pX = 4;

int** ppX = &pX:

**ppX = 3;
---

I know exactly how references "behave", but I want to know how they actually
work!

For instance, take the following function:

void Repot(unsigned int* pX)
{
*pX = 45U;
}
The caller will do the following:

int main(void)
{
unsigned int X = 17U;

Repot(&X);
}
Obviously one could rewrite the above code as:
void Repot(unsigned int& X)
{
X = 45U;
}
int main(void)
{
unsigned int X = 17;

Repot(X);
}
But what I want to know is what's actually going on under the hood. One
quick little side note here though before I continue: When I first learned
about references, I detested them, I thought they were extremely stupid. One
may argue that they're easier to use, just as one may argue that an
automatic transmission car is easier to driver, but long story short, I
prefer manual transmission and detest references. So anyway, I could find no
justification for the introduction of references into C++, other than to
make operator overloading for classes possible. I was pleasantly amused when
I heard a quote from Bjarne himself stating that the reason he introduced
references into C++ was to enable operator overloading for classes. Fair
enough, and although in my opinion it is heavily contrived, it works! Just
for clarification, here's what I hate so much about references: Before, when
calling a function, you could specify "X" to indicate the value stored in
the variable, and you could specify "&X" to indicate the memory address of
the variable. With references, this is no longer so. (Yes, I am aware that
one can determine from the function prototype whether or not it's a
reference... I don't like it).

So anyway, how does the compiler deal with references? Does it simply treat
them as short-hand? Would the compiler turn my preceeding code (written
using references) back into pointers? ie. would it simply stick in the "*"
and "&" where appropriate? If the answer to this is Yes, then I pressume
that both samples of code would compile identically and hence allocate the
same amount of memory. (That is, the use of a reference does not supress the
need to have another variable within which to store the address of another
variable, ie. a pointer variable). If this is so, everything is fine and
dandy and I understand references, regardless of whether I like them. If
this is NOT so, I am at a loss! Before, I used to just think of it as
follows: If a function has a reference as a parameter, then you can think of
it as the scope of the variable being extended to the function which has
been called. This concept worked fine for me until I came across functions
whose return type was a reference. This is where my brain started
stuttering. Take the function prototype:

unsigned int& TeachFarmAnimals(void);

When you call the above function, what exactly are you getting back as a
return type?!! Are you simply receiving a pointer, and is the compiler just
sticking in the "*" and "&" for you where appropriate?
In summation:

Are references just pointers without the need to include "&" and "*", and is
the compiler just handling the "&" and "*" for you in the background?
-JKop
Jul 22 '05 #1
Share this Question
Share on Google+
33 Replies


P: n/a
On Sun, 16 May 2004 19:19:54 GMT, JKop <NU**@NULL.NULL> wrote in
comp.lang.c++:

I understand variables/objects and pointer variables perfectly:

int X = 5;

int* pX = &X;

*pX = 4;

int** ppX = &pX:

**ppX = 3;
---

I know exactly how references "behave", but I want to know how they actually
work!
They work very well, thank you.

[snip]
But what I want to know is what's actually going on under the hood.


Unfortunately, you are asking in the wrong place. The C++ standard
does not specify what goes on "under the hood". The standard defines
the interface to the programmer and the behavior when used correctly.
It places no requirements at all on the implementation as to how it
delivers the correct results. Nor is it necessary to for one to know
the details to write a correct C++ program.

If you want to understand how a specific compiler does these things,
study the object code it generates. If you want to discuss the
possible mechanisms in general, try news:comp.compilers.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 22 '05 #2

P: n/a

"JKop" <NU**@NULL.NULL> wrote in message
news:u9******************@news.indigo.ie...

I understand variables/objects and pointer variables perfectly:

int X = 5;

int* pX = &X;

*pX = 4;

int** ppX = &pX:

**ppX = 3;
---

I know exactly how references "behave", but I want to know how they actually work!

For instance, take the following function:

void Repot(unsigned int* pX)
{
*pX = 45U;
}
The caller will do the following:

int main(void)
{
unsigned int X = 17U;

Repot(&X);
}
Obviously one could rewrite the above code as:
void Repot(unsigned int& X)
{
X = 45U;
}
int main(void)
{
unsigned int X = 17;

Repot(X);
}
But what I want to know is what's actually going on under the hood. One
quick little side note here though before I continue: When I first learned
about references, I detested them, I thought they were extremely stupid. One may argue that they're easier to use, just as one may argue that an
automatic transmission car is easier to driver, but long story short, I
prefer manual transmission and detest references. So anyway, I could find no justification for the introduction of references into C++, other than to
make operator overloading for classes possible. I was pleasantly amused when I heard a quote from Bjarne himself stating that the reason he introduced
references into C++ was to enable operator overloading for classes. Fair
enough, and although in my opinion it is heavily contrived, it works! Just
for clarification, here's what I hate so much about references: Before, when calling a function, you could specify "X" to indicate the value stored in
the variable, and you could specify "&X" to indicate the memory address of
the variable. With references, this is no longer so. (Yes, I am aware that
one can determine from the function prototype whether or not it's a
reference... I don't like it).
You're missing out on two important aspect of references, one aesthetic, one
practical.

From the aesthetic point of view the chief difference between pointers and
references is that references always refer to the same object, unline
pointers. So if you need to refer to some object, and that reference (in the
general sense) is never going to refer to another object during its lifetime
you should consider using a reference (in the C++ sense) because it better
expresses what you are doing.

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

class X;

void f1(const X*);
void f2(X);
void f3(const X&);
X g();

f1(&g()); // illegal

X t = g();
f1(&t); // ugly temp variable, extra copy

f2(g()); // extra copy, may or may not be optimised by compiler

f3(g()); // perfect


So anyway, how does the compiler deal with references? Does it simply treat them as short-hand? Would the compiler turn my preceeding code (written
using references) back into pointers? ie. would it simply stick in the "*"
and "&" where appropriate?


Almost certainly, so certain am I that I've always assumed this to be the
case on every compiler I've ever used, and haven't actually bothered to
check. The only way to be sure would be to have a look at the machine code
your compiler generates.

john
Jul 22 '05 #3

P: n/a


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.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.
It's like a const pointer variable, ie. you must initialize it upon
declaration:

int m = 5;

int* const pM = &m;

int& j = m;
Andt the second and final difference is that you treat it like a normal
variable, ie. you don't use the asterisk to access its data. And again, like
a normal variable, if you get the address of it, you get back an "int*", as
opposed to an "int**". It's so clear in my mind now. I fully understand:

Car& Porsche = *(new Car);

delete &Porsche;
and it's much more beautiful than:

Car* pPorsche = new Car;

delete pPorsche;
That is, you can work with a "Car", and not with a "Car*"!!
And similarly, when a function returns a reference:

int& GetApe(void);
It's returning a const pointer that you can treat as an "int" as opposed to
an "int*".
John Harrison, you said that an reference can also bind to a temporary, and
that's cool too, but just for clarity, so can a pointer. Consider the
following tested code:
long double Monkey(void)
{
return 87.343;
}

void Chocolate(long double* pTermite)
{
*pTermite = 56.242;

std::cout << *pTermite;
}

int main(void)
{
long double k;

Chocolate(&(k = Monkey()));

system("PAUSE");
return 0;
}

The temporary in the above is valid, right?
-JKop

Jul 22 '05 #4

P: n/a
JKop posted:
John Harrison, you said that an reference can also bind to a temporary,
and that's cool too, but just for clarity, so can a pointer. Consider
the following tested code:
long double Monkey(void)
{
return 87.343;
}

void Chocolate(long double* pTermite)
{
*pTermite = 56.242;

std::cout << *pTermite;
}

int main(void)
{
long double k;

Chocolate(&(k = Monkey()));

system("PAUSE");
return 0;
}

The temporary in the above is valid, right?

I TOTALLY dropped the ball there!! I'm making a copy of the temporary via:

k = Monkey();
Duh!!!
I see what you're getting at, John Harrison, that you simply can't get the
address of a temporary, ie:

&(Monkey())

The above doesn't compile. Yet, a reference *will* get the address!!
-JKop
Jul 22 '05 #5

P: n/a
JKop writes:
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.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.


What so you call a variable that can't be changed in your world?
Jul 22 '05 #6

P: n/a
osmium posted:
JKop writes:
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.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.


What so you call a variable that can't be changed in your world?


Ignoring your grammar...
I was given vague descriptions like so:
A reference is used so a function can edit the variable passed to it:

void Monkey(int& j)
{
j = 5;
}
It never actually just stated that a reference is just a const pointer
variable that's treated like a domestic non-pointer variable.

-JKop
Jul 22 '05 #7

P: n/a
JKop wrote:

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.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.


Wrong.
A reference is just another name for a variable.

Your compiler might use a pointer internally to represent it, but
it need not. Nevertheless the thinking model of a 'hidden pointer'
is a good one. But there is a difference between a mental model
and what things really are. References are alternative names.
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #8

P: n/a
Karl Heinz Buchegger wrote:

JKop wrote:

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.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.


Wrong.
A reference is just another name for a variable.


Also wrong:

A reference is just another name for an object (it need not be a variable)

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #9

P: n/a
Karl Heinz Buchegger posted:
Wrong.
A reference is just another name for a variable.

Your compiler might use a pointer internally to represent it, but
it need not. Nevertheless the thinking model of a 'hidden pointer'
is a good one. But there is a difference between a mental model
and what things really are. References are alternative names.

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 ?

Pointers is what they are, and on a 32-Bit Memory Model platform, sizeof
(Jeep) will be 64 Bits, which proves my point.
int main(void)
{
Vector j;
Vector k;

Jeep jeep = {j, k};
}
Jul 22 '05 #10

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

By which I mean:

struct Candy
{
long double& a;
long double& b;
long double& c;
};
The following statement will be true:
sizeof(Candy) == 3 * sizeof(void*);
Jul 22 '05 #11

P: n/a
JKop wrote:
JKop posted:

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

No, it doesn't.
By which I mean:

struct Candy
{
long double& a;
long double& b;
long double& c;
};
The following statement will be true:
sizeof(Candy) == 3 * sizeof(void*);

Look, kid, you don't know half as much as you think you do. Stop
arguing with people who have more experience and a hell of a lot more
knowledge than you have.
Jul 22 '05 #12

P: n/a
JKop wrote:
JKop posted:

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


By which I mean:

struct Candy
{
long double& a;
long double& b;
long double& c;
};
The following statement will be true:
sizeof(Candy) == 3 * sizeof(void*);


It might be true on whatever system you're compiling, but it is not true
in a general sense.

As well pointed out by other people, references are better thought of as
aliases.

By this I mean.

int a;
int &b = a;

Now you can modify either a or b, and you are affecting the same object.

Since a and b refer to the same object in the example above,
then &a == &b.

This leads to your notion of a "pointer variable".

However, please notice the difference. A pointer is a number that
represents a memory location. A reference is an object. It just refers
to an already existing object...

JLR
Jul 22 '05 #13

P: n/a
>>>A reference variable is just a pointer variable.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.

I think I have to agree. JKop!
"Jorge Rivera" <jo*****@rochester.rr.com> wrote in message
news:M3******************@twister.nyroc.rr.com...
This leads to your notion of a "pointer variable".

However, please notice the difference. A pointer is a number that
represents a memory location. A reference is an object. It just refers
to an already existing object...


And that is different to a "constant pointer variable" in what way...?
--
Mabden
Jul 22 '05 #14

P: n/a
Jeff Schwab posted:
Look, kid, you don't know half as much as you think you do. Stop
arguing with people who have more experience and a hell of a lot more
knowledge than you have.

Fascist
-JKop

Jul 22 '05 #15

P: n/a
Jorge Rivera posted:
However, please notice the difference. A pointer is a number that
represents a memory location. A reference is an object. It just refers
to an already existing object...

int hedgehog = 4;
int* const pZebra = &hedgehog;
int& zebra = hedgehog;
*pZebra = 17;
zebra = 17;
void Sack(int*);
Sack( pZebra );
Sack( &zebra );
int porcupine = 8;

pZebra = &Porcupine; //ERROR, cannot assign to const variable

zebra = //Can't even try

-JKop
Jul 22 '05 #16

P: n/a
Mabden wrote:
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.
A reference variable is just a pointer variable.

I think I have to agree. JKop!
"Jorge Rivera" <jo*****@rochester.rr.com> wrote in message
news:M3******************@twister.nyroc.rr.com...

This leads to your notion of a "pointer variable".

However, please notice the difference. A pointer is a number that
represents a memory location. A reference is an object. It just refers
to an already existing object...

And that is different to a "constant pointer variable" in what way...?


In that a reference isn't a variable at all.

A pointer is a variable in its own right. A reference is not. Pointers
have their own addresses in memory. If a compiler doesn't optimize
pointers away, they will exist at run-time.

A reference does not have its own address. Sometimes pointers are used
"behind the scenes" to implement reference semantics, as in the case
JKop mentioned of a struct containing references. These supporting
pointers are what take up the space JKop noticed. However, a reference
is primarily a new name used to refer to an existing variable (which may
or may not have a different name already).

I know this is subtle, so it's understandable if the difference still
isn't clear. Here's an example of a place where the differences between
"const pointers" and references mean that one can be used where the
other cannot:

int main ( )
{
typedef void* const Pointer_to_void;
typedef void& Reference_to_void;
}
Jul 22 '05 #17

P: n/a
> zebra = //Can't even try


Of couse not. References are initialized once, as dictated by the
standard, hence your compilers will whine endlessly...

Jorge L.
Jul 22 '05 #18

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


No, it doesn't.

class BankAccountInfoPointers
{
unsigned long int* const serial_number;
unsigned short int* const number_of_owners;
};
class BankAccountInfoReferences
{
unsigned long int& serial_number;
unsigned short int& number_of_owners;
};

Can anyone here suggest any reason at all why the following expression would
be false?:
sizeof(BankAccountInfoPointers) == sizeof(BankAccountInfoReferences)

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

-JKop
Jul 22 '05 #19

P: n/a
JKop wrote:
Jeff Schwab posted:

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


No, it doesn't.


class BankAccountInfoPointers
{
unsigned long int* const serial_number;
unsigned short int* const number_of_owners;
};
class BankAccountInfoReferences
{
unsigned long int& serial_number;
unsigned short int& number_of_owners;
};

Can anyone here suggest any reason at all why the following expression would
be false?:
sizeof(BankAccountInfoPointers) == sizeof(BankAccountInfoReferences)

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


No, who said the size of the structs would be different? The matching
size does not mean that references are the same as constant pointers,
though.
Jul 22 '05 #20

P: n/a
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.
Jul 22 '05 #21

P: n/a
Mabden wrote:

"Jorge Rivera" <jo*****@rochester.rr.com> wrote in message
news:mH*******************@twister.nyroc.rr.com...
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.


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.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #22

P: n/a
JKop wrote:

Karl Heinz Buchegger posted:
Wrong.
A reference is just another name for a variable.

Your compiler might use a pointer internally to represent it, but
it need not. Nevertheless the thinking model of a 'hidden pointer'
is a good one. But there is a difference between a mental model
and what things really are. References are alternative names.
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.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #23

P: n/a
JKop <NU**@NULL.NULL> wrote:
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.
Jul 22 '05 #24

P: n/a
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
Jul 22 '05 #25

P: n/a
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
Jul 22 '05 #26

P: n/a
JKop wrote in news:bi*****************@news.indigo.ie in comp.lang.c++:
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;


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/de...uct_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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #27

P: n/a
JKop wrote:
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.


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.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #28

P: n/a
JKop wrote:

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!


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.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #29

P: n/a
"Karl Heinz Buchegger" <kb******@gascad.at> wrote in message
news:40***************@gascad.at...
JKop wrote:

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!


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

--
Mabden
Jul 22 '05 #30

P: n/a
Mabden wrote:
int* k;
Parrot( &( *k = Monkey() ) );
[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.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #31

P: n/a
Karl Heinz Buchegger posted:
JKop wrote:

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!


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
Jul 22 '05 #32

P: n/a
JKop wrote:
Karl Heinz Buchegger posted:

JKop wrote:
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;
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.
Parrot( &( *k = Monkey() ) );


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).
Jul 22 '05 #33

P: n/a
Luther Baker posted:
JKop wrote:
Karl Heinz Buchegger posted:

JKop wrote:

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;


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
Jul 22 '05 #34

This discussion thread is closed

Replies have been disabled for this discussion.