views:

123

answers:

4

if I have a function like that:

void doSomething(int& aVar)
{
// do something
}

and I have this:

int *aVar = new int;
*aVar = 10;

doSomething(*aVar);

Why should I call *aVar? isn't aVar already an address?

+8  A: 

No, a reference is not a pointer. References are guaranteed to not be null; you cannot say the same for a pointer. When you pass an int to a function that expects an int& the reference will be taken automatically.

P.S. Don't think of it as an address or a fancy pointer. It is a reference, or an alias to an existing object.

Ed Swangren
To be pedantic, I'd say "...alias to an existing value", not object.
GMan
@Gman: an alias to an instance.
Captain Giraffe
+1 comment point for you GMan, an int is obviously not an object ;)
Ed Swangren
@Captain: AFAIK, "instance" is synonymous with "object". @Ed: Actually, `int` is an object. An "object" is a "region of storage". @All: I say value and not object because, for example, in `int i = 5; const int` we are referencing a value of 5, but no object (it's an rvalue.)
GMan
An int *is* an object. It does not have class type (sometimes said "not an instance of a class"), but conventional terminology and standardese agrees: int variables and temporaries are objects.
Roger Pate
I don't see a clear definition in C++03, but §3.1p6 uses the term generally and refers to §3.9, which says (p1, which is a note) "Types describe objects (1.8), references (8.3.2), or functions (8.3.5)." Additionally, §3p4 says "A variable is introduced by the declaration of an object," which, although it doesn't cover temporaries, may be the clearest.
Roger Pate
@GMan: an rvalue (as in `(i + 0)`) is another way of saying temporary object. You cannot take a reference to it because it is short-lived. It has a value, which can be found in the temporary location it would reference.
TokenMacGuy
@Token: Indeed, rather obvious error on my part.
GMan
Ok, I was loose with my terminology. I guess it is a remnant of C++ not being my first language. I tend to think of an object as a class or struct type, and everythign else as primitive types. If I cant do 1.SomeMethod() I don't think of it as an object. Obviously that is not necessarily true.
Ed Swangren
What guarantees they aren't NULL? I can get this to compile and run: int* foo = NULL; doSomething(*foo);
Scott S
@Scott: Just because it compiles and runs doesn't mean it works. When you dereference a null pointer, you get undefined behavior.
GMan
Yeah, welcome to the real world where there is no one to hold your hand at every turn ;)
Ed Swangren
Scott S
No, they are guaranteed to not be null. When you dereference a NULL pointer you are not passing in NULL, you are passing in soemthign that is undefined.
Ed Swangren
You are confusing a null pointer with the result of dereferencing a null pointer. Two different things.
Ed Swangren
GMan
@Scott: How would you propose that the compiler stop you from invoking undefined behavior? How could it possible know that a null pointer will never be dereferenced?
Ed Swangren
I'm not proposing the compiler stop you from invoking undefined behavior. But saying that the reference is guaranteed not to be NULL is misleading. If you try to access a member variable of the converted-from NULL reference, you will get an access violation. If you try to access a member variable with offset 0, you will get an access violation at memory location 0. The reference isn't some magical thing - manipulating a reference is equivalent underneath to working with pointer arithmetic. So there are no guarantees.
Scott S
@GMan - Let's not be pedantic. Yes, the language spec says the result of dereferencing a NULL pointer is undefined behavior. But in practice, converting a NULL pointer into a reference happily compiles and runs on all the major platforms I'm aware of (it's impossible to determine this at compile time in all cases). So the 'guarantee' that references will not be NULL is pretty meaningless.
Scott S
My main objection to this answer is that the answer's main claim about the differences between references and pointers isn't true in practice. Much more accurate would be to talk more about how a reference is an alias, and the consequences - like the fact it must be initialized at declaration time and cannot be rebound to another object.
Scott S
@Scott: You still seem unable to understand what "unspecified behavior" means. The standard can certainly guarantee that a reference will not be null because it assumes that your program is not invoking undefined behavior. If you do, then all bets are off and *nothing* in the standard can be guaranteed. There is nothing "pedantic" about it.
Ed Swangren
@Scott: Your usage of "but" in "But in practice" shows a misunderstanding on your part. There's no "but" anything. It's undefined behavior, any compiler is allowed to perform any action. What's the "but" objecting when there's nothing to object? Again: references cannot be null. I'll also say welcome to C++; it's a pedantic language, you'll have to get used to that. Please answer this question: how can you conclusively determine, within the C++ language, that a reference is null? If you can't, you have no basis for claiming references can be null. This isn't up for debate, it's not a mystery.
GMan
+2  A: 
doSomething(int&)

wants a reference not a pointer. The way to set up that reference as a parameter is to pass in an Int. Which is why

doSomething(*aVar)

works. If you want to use a pointer in the function say

doSomething(int*)

references and pointers are not the same thing (although they have a lot in common)

pm100
A: 

A pointer is pointing to a specific memory address and a pointer has it's own data (ie the memory address it's pointing to). When you pass aVar to the function without dereferencing (the * operator) the pointer you would be passing the memory location of the pointer, not the memory location the pointer is pointing to.

GWW
+1  A: 

The asterisk, besides multiplication has two meanings:

a) When declaring a variable: *x means "X is a pointer" b) When using a variable: *x (when x is of pointer type) means "take whatever is pointed by x" - the opposite of &x, which means "take the address of x".

The code:

doSomething(*aVar)

just wants to dereference the pointer "aVar" (take the value of type int pointed by it) and pass this value of type int as a parameter to the function.

The variable "aVar" stores an address of some integer value, not the value itself, so you have to use the "*" operator to dereference it every time you want to access the integer, not the memory address itself.

References in C++ are quite counter-intuitive ("disguised pointers"), so if doSomething takes a reference to int, you have to call it as if you were passing an actual int value, not a pointer. Hence you need the dereference operator.

Kos