What is the difference between the following two parameter types? The first accepts a pointer, which is in effect a memory address, and the second is also a memory address?
foo(float& bar)
{
// do stuff
}
foo(float* bar)
{
// do stuff
}
Could you not call both with:
float pow = 3.0f;
foo(&pow);
or
float* pow = 3.0f;
foo(pow);
A pointer can be NULL, while a reference can't. This can be useful if you need to pass a NULL object for whatever reason.
With the pointer syntax, you pass a pointer when you call the function. With references, you just pass the variable:
refer(float& bar) {}
point(float* bar) {}
float afloat = 1.0f;
refer(afloat);
point(&afloat);
This means with the pointer syntax you have to pass a pointer when you call the function. With the reference syntax, you don't know if the function takes it by reference or by value without looking at the function definition.
With the reference syntax you don't have to dereference the pointer in your function, and work with it more naturally in your // do stuff section.
foo(float& bar)
{
bar = 3.0f;
}
// versus
foo(float* bar)
{
*bar = 3.0f;
}
No, they are not the same. The first is taking a parameter by reference and would be called like this:
float pow = 3.0f;
foo(pow) // foo can change the value of pow!
the second accepts a pointer and could be called by either of your examples (both of which are passing a pointer, not a reference).
NOTE: your second example, while it passes a float* does not properly initialize the pow variale, and therefore won't compile. Instead, something like this would work:
float *pow = new float(3.0);
foo(pow);
delete pow;
While references have similarities to pointers, it is not mandated that they are implemented internally by pointers. For example, often the compiler can inline calls and just modify the argument directly, no pointer passed in that case.
In general, think of a reference as "just another name" for a variable. For example:
Person Samuel_Clemens;
Person &Mark_Twain(Samuel_Clemens); // just another name
The difference is that the first cannot receive a null pointer, while the second can.
But with a bit of effort you can make the first receive null pointer too:
float *a = null;
pow(*a);
Edit: All the following proved to be wrong, I'll keep it as reference for the comments:
The difference is that the reference version will throw an exception when dereferencing a null reference while pointer version will just segfault:
float *a = null;
float &b = *a; // works... somehow?
b = 1; // throws exception
*a = 1; // segmentation fault
float* is a pointer to a float number, whereas float& is a reference to a float number.
With a pointer, you can say function(null) letting the argument point to null (which represents nothing in particular, and often causes undefined behaviour (=crash)). A reference can't reference to nothing (at least not that easy).
When using float*, you will always treat this argument as a pointer, and the compiler does as well. When you use float&, you can treat it as a "normal" (i.e. non-pointer) variable, but it is as if you were using a pointer.
In the first (reference), you are interested on reading and writing the original variable. In the secondth (pointer), you are interested on receiving the address of the original variable.
The difference is mostly taste, except the fact that the pointer version allows you to not-pass any value using a NULL value.
Related
What is the purpose of a function parameter that has two indirection operators?
Since a call by reference is changing the value of the original variable I thought that a function parameter with two indirection operators might change the address of the original value.
But as my attemp below shows, it does not:
void addrchanger(int**);
int main()
{
int value1 = 4;
int* value1ptr = &value1;
std::cout<<&value1<<std::endl;
addrchanger(&value1ptr);
std::cout<<&value1<<std::endl;
//the address of value1 doesn't change.
}
void addrchanger(int** foo)
{
//this is an attempt to change the address of value1 to the next slot
++**foo;
}
The purpose is to pass a pointer to pointer(s) or a pointer to array(s). Such practise is C-like for historical functions like main() char** argv (that is why you also want an argc, because the size cannot be deduced by the pointer). It is also used when you want to be returned a pointer, so you pass a pointer to a pointer, like in many Win32 functions.
For example in StringFromIID
HRESULT StringFromIID(
REFIID rclsid,
LPOLESTR *lplpsz
);
you would pass a double pointer as the 2nd parameter (a wchar_t**) in order to be returned a pointer, which them must be deallocated like the doc says.
Avoid that completely nowadays in C++ and use std::vector in whatever depth is necessary.
The void addrchanger(int** foo) function can change:
the value: (**foo)++ making int value1 to 5
and address: (*foo)++ making value1ptr point to the next space after value1
I believe you expected the ++**foo to move value1 to the next position, which is not the case.
The pointer to pointer is also useful for matrix declarations, but most libraries such as the GNU scientific library, BLAS, OpenGL glLoadMatrixf(), prefer the use of a single pointer.
When p is of type int **,
++**p
increases the value of the int represented by **p.
In order to change the address of the int pointed to, you would use
++*p
With direct access to your variable, you would use one * less for everything:
int *p;
++*p; // increment the int value
++p; // increment the pointer
But inside such a function, every arguments is just a copy, so if you want to change something outside, you need a pointer to it, which means that one more * is used for everything.
function f(int **p) {
++**p; // increment the int value
++*p; // increment the pointer
// you can also increment the argument
// but you can't know whether it will then
// still point to another int pointer:
++p
}
In addition, you can use & instead of * in C++ which is used only for declaring a variable as a reference and then works like a secret, hidden pointer. You use one less * again, like outside the function at the beginning.
function f(int *&p) {
++*p; // increment the int value
++p; // increment the pointer
// you can also not increment the reference itself,
// as it is a hidden pointer.
}
This sounds dangerous because who would want secret pointers? But it is very common in C++ because people like typing less * all over the place.
I'm learning C and I'm still not sure if I understood the difference between & and * yet.
Allow me to try to explain it:
int a; // Declares a variable
int *b; // Declares a pointer
int &c; // Not possible
a = 10;
b = &a; // b gets the address of a
*b = 20; // a now has the value 20
I got these, but then it becomes confusing.
void funct(int a) // A declaration of a function, a is declared
void funct(int *a) // a is declared as a pointer
void funct(int &a) // a now receives only pointers (address)
funct(a) // Creates a copy of a
funct(*a) // Uses a pointer, can create a pointer of a pointer in some cases
funct(&a) // Sends an address of a pointer
So, both funct(*a) and funct(&a) are correct, right? What's the difference?
* and & as type modifiers
int i declares an int.
int* p declares a pointer to an int.
int& r = i declares a reference to an int, and initializes it to refer to i.
C++ only. Note that references must be assigned at initialization, therefore int& r; is not possible.
Similarly:
void foo(int i) declares a function taking an int (by value, i.e. as a copy).
void foo(int* p) declares a function taking a pointer to an int.
void foo(int& r) declares a function taking an int by reference. (C++ only)
* and & as operators
foo(i) calls foo(int). The parameter is passed as a copy.
foo(*p) dereferences the int pointer p and calls foo(int) with the int pointed to by p.
foo(&i) takes the address of the int i and calls foo(int*) with that address.
(tl;dr) So in conclusion, depending on the context:
* can be either the dereference operator or part of the pointer declaration syntax.
& can be either the address-of operator or (in C++) part of the reference declaration syntax.
Note that * may also be the multiplication operator, and & may also be the bitwise AND operator.
funct(int a)
Creates a copy of a
funct(int* a)
Takes a pointer to an int as input. But makes a copy of the pointer.
funct(int& a)
Takes an int, but by reference. a is now the exact same int that was given. Not a copy. Not a pointer.
void funct(int &a) declares a function that takes a reference. A reference is conceptually a pointer in that the function can modify the variable that's passed in, but is syntactically used like a value (so you don't have to de-reference it all the time to use it).
Originally in C there were pointers and no references. Very often though we just want to access a value without copying it and the fact that we're passing around an address and not the actual value is an unimportant detail.
C++ introduced references to abstract away the plumbing of pointers. If you want to "show" a value to a function in C++ then references are preferable. The function is guaranteed that a reference is not null and can access it as if it were the value itself. Pointers are still necessary for other purposes, for example, you can "re-aim" a pointer or delete with a pointer but you can't do so with a reference.
Their functionality does overlap and without a bit of history it should confuse you that we have both.
So the answer to your direct question is that very often there is no difference. That said, f(int*) can be useful if you want the function to be able to check if the pointer is null. If you're using C then pointers are the only option.
The meaning of * is dependent on context. When in a data or function argument declaration, it is a datatype qualifier, not an operator int* is a datatype in itself. For this reason it is useful perhaps to write:
int* x ;
rather than:
int *x ;
They are identical, but the first form emphasises that it the * is part of the type name, and visually distinguishes it from usage as dereference operator.
When applied to an instantiated pointer variable, it is the dereference operator, and yields the the value pointed to.
& in C is only an operator, it yields the address (or pointer to) of an object. It cannot be used in a declaration. In C++ it is a type qualifier for a reference which is similar to a pointer but has more restrictive behaviour and is therefore often safer.
Your suggestion in the comment here:
funct(&a) // Sends an address of a pointer
is not correct. The address of a is passed; that would only be "address of a pointer" is a itself is a pointer. A pointer is an address. The type of an address of a pointer to int would be int** (a pointer to a pointer).
Perhaps it is necessary to explain the fundamentals of pointer and value variables? A pointer describes the location in memory of a variable, while a value describes the content of a memory location.
<typename>* is a pointer-to-<typename> data type.
&*<value-variable> yields the address or location of <variable> (i.e. a pointer to <variable>),
**<pointer-variable> dereferences a pointer to yield the the value at the address represented by the pointer.
So given for example:
int a = 10 ;
int* pa = &a ;
then
*pa == 10
When you do func(&a) that's called a "call by reference" that means your parameter "a" can actually be modified within the function and any changes made will be visible to the calling program.
This is a useful way if you want to return multiple values from a function for example:
int twoValues(int &x)
{
int y = x * 2;
x = x + 10;
return y;
}
now if you call this function from your main program like this:
int A, B;
B = 5;
A = twoValues(B);
This will result in:
A holding the value 10 (which is 5 * 2)
and B will hold the value 15 (which is 5 + 10).
If you didn't have the & sign in the function signature, any changes you make to the parameter passed to the function "twoValues" would only be visible inside that function but as far as the calling program (e.g. main) is concerned, they will be the same.
Now calling a function with a pointer parameter is most useful when you want to pass an array of values or a list. Example:
float average ( int *list, int size_of_list)
{
float sum = 0;
for(int i = 0; i < size_of_list; i++)
{
sum += list[i];
}
return (sum/size_of_list);
}
note that the size_of_list parameter is simply the number of elements in the array you are passing (not size in bytes).
I hope this helps.
C++ is different from c in many aspects and references is a part of it.
In terms of c++ context:
void funct(int *a) // a is declared as a pointer
This corelates to the use of pointers in c..so, you can compare this feature to that of c.
void funct(int &a) // a now receives only pointers (address)
This would lead to the reference usage in c++...
you cannot corelate this to that of c..
Here is a good q&a clarifying differences between these two.
What are the differences between a pointer variable and a reference variable in C++?
What does it mean? I understand the use of pass by reference is to pass in the reference so you can directly alter it without the need of a return, and pass by pointer is similar but with a slower runtime. However, I do not understand what * & does. For an example,
foo(int * & var) { }
It passes a pointer by reference so that you can change what the pointer points to and have those changes reflected to the caller.
For example:
void notByReference(int *p) {
p = nullptr;
}
void byReference(int *&p) {
p = nullptr;
}
int main() {
int *i = new int;
notByReference(i); //i is not changed since a copy of the pointer was passed
byReference(i); //i itself is changed, leaking memory
}
This allows you to pass a pointer by reference. Which gives the function the opportunity to modify the pointer and have that modification seen by the caller.
You don't need to stop there. You can pass by reference a pointer to pointer to int, for example.
void foo(int** &var)
Keep in mind that type qualifiers like & and * are independent of each other. When you see some_type& it simply means "reference to sometype", which in turn means that the function sees the caller's version of the argument and can modify it. When sometype is a pointer it just means that the type of the caller's version of the argument is a pointer, and the function can modify that pointer.
What exactly does implicit dereference in C++ mean? Does it mean when I pass a reference to variable into a function parameter I don't need the & in front of it to use its value?
I assume that your teacher was trying to explain the difference between pointers and references.
It is relatively common (though not technically accurate) to refer to references as fancy pointers that do implicit de-referencing.
int x = 5;
int* xP = &x;
int& xR = x;
xR = 6; // If you think of a reference as a fancy pointer
// then here there is an implicit de-reference of the pointer to get a value.
*xP = 7; // Pointers need an explicit de-reference.
The correct way to think about is not to use the "A reference is a fancy pointer". You need to think about references in their own terms. They are basically another name for an existing variable (AKA an alias).
So when you pass a variable by reference to a function. This means the function is using the variable you passed via its alias. The function has another name for an existing variable. When the function modifies the variable it modifies the original because the reference is the original variable (just another name for it).
So to answer you question:
I don't need the & in front of it to use its value?
No you don't need to add the &.
int f(int& x) // pass a value by reference
{
x =5;
}
int plop = 8;
f(plop);
// plop is now 5.
Another context in which C++ will implicitly dereference pointers is with function pointers:
void foo() { printf("foo\n"); }
void bar() {
void (*pf)() = &foo;
(*pf)(); // Explicit dereference.
pf(); // Implicit dereference.
}
I have a fairly good understanding of the dereferencing operator, the address of operator, and pointers in general.
I however get confused when I see stuff such as this:
int* returnA() {
int *j = &a;
return j;
}
int* returnB() {
return &b;
}
int& returnC() {
return c;
}
int& returnC2() {
int *d = &c;
return *d;
}
In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?
In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?
In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically "appended" c?
In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?
Assume a, b, c are initialized as integers as Global.
Can someone validate if I am correct with all four of my questions?
Although Peter answered your question, one thing that's clearly confusing you is the symbols * and &. The tough part about getting your head around these is that they both have two different meanings that have to do with indirection (even excluding the third meanings of * for multiplication and & for bitwise-and).
*, when used as part of a type
indicates that the type is a pointer:
int is a type, so int* is a
pointer-to-int type, and int** is a
pointer-to-pointer-to-int type.
& when used as part of a type indicates that the type is a reference. int is a type, so int& is a reference-to-int (there is no such thing as reference-to-reference). References and pointers are used for similar things, but they are quite different and not interchangable. A reference is best thought of as an alias, or alternate name, for an existing variable. If x is an int, then you can simply assign int& y = x to create a new name y for x. Afterwords, x and y can be used interchangeably to refer to the same integer. The two main implications of this are that references cannot be NULL (since there must be an original variable to reference), and that you don't need to use any special operator to get at the original value (because it's just an alternate name, not a pointer). References can also not be reassigned.
* when used as a unary operator performs an operation called dereference (which has nothing to do with reference types!). This operation is only meaningful on pointers. When you dereference a pointer, you get back what it points to. So, if p is a pointer-to-int, *p is the int being pointed to.
& when used as a unary operator performs an operation called address-of. That's pretty self-explanatory; if x is a variable, then &x is the address of x. The address of a variable can be assigned to a pointer to the type of that variable. So, if x is an int, then &x can be assigned to a pointer of type int*, and that pointer will point to x. E.g. if you assign int* p = &x, then *p can be used to retrieve the value of x.
So remember, the type suffix & is for references, and has nothing to do with the unary operatory &, which has to do with getting addresses for use with pointers. The two uses are completely unrelated. And * as a type suffix declares a pointer, while * as a unary operator performs an action on pointers.
In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?
Yes, int *j = &a initializes j to point to a. Then you return the value of j, that is the address of a.
In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?
Yes. Here the same thing happens as above, just in a single step. &b gives the address of b.
In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically appended?
No, it is a reference to an int which is returned. A reference is not an address the same way as a pointer is - it is just an alternative name for a variable. Therefore you don't need to apply the & operator to get a reference of a variable.
In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?
Again, it is a reference to an int which is returned. *d refers to the original variable c (whatever that may be), pointed to by c. And this can implicitly be turned into a reference, just as in returnC.
Pointers do not in general point to an address (although they can - e.g. int** is a pointer to pointer to int). Pointers are an address of something. When you declare the pointer like something*, that something is the thing your pointer points to. So in my above example, int** declares a pointer to an int*, which happens to be a pointer itself.
Tyler, that was very helpful explanation, I did some experiment using visual studio debugger to clarify this difference even further:-
int sample = 90;
int& alias = sample;
int* pointerToSample = &sample;
Name Address Type
&alias 0x0112fc1c {90} int *
&sample 0x0112fc1c {90} int *
pointerToSample 0x0112fc1c {90} int *
*pointerToSample 90 int
alias 90 int &
&pointerToSample 0x0112fc04 {0x0112fc1c {90}} int * *
Memory Layout
PointerToSample Sample/alias
_______________......____________________
0x0112fc1c | | 90 |
___________|___.....__|________|_______...
[0x0112fc04] ... [0x0112fc1c
In returnC() and returnC2() you are not asking to return the address.
Both these functions return references to objects.
A reference is not the address of anything it is an alternative name of something (this may mean the compiler may (or may not depending on situation) use an address to represent the object (alternatively it may also know to keep it in register)).
All you know that a reference points at a specific object.
While a reference itself is not an object just an alternative name.
All of your examples produce undefined run-time behavior. You are returning pointers or references to items that disappear after execution leaves the function.
Let me clarify:
int * returnA()
{
static int a; // The static keyword keeps the variable from disappearing.
int * j = 0; // Declare a pointer to an int and initialize to location 0.
j = &a; // j now points to a.
return j; // return the location of the static variable (evil).
}
In your function, the variable j is assigned to point to a's temporary location. Upon exit of your function the variable a disappears, but it's former location is returned via j. Since a no longer exists at the location pointed to by j, undefined behavior will happen with accessing *j.
Variables inside functions should not be modified via reference or pointer by other code. It can happen although it produces undefined behavior.
Being pedantic, the pointers returned should be declared as pointing to constant data. The references returned should be const:
const char * Hello()
{
static const char text[] = "Hello";
return text;
}
The above function returns a pointer to constant data. Other code can access (read) the static data but cannot be modified.
const unsigned int& Counter()
{
static unsigned int value = 0;
value = value + 1;
return value;
}
In the above function, the value is initialized to zero on the first entry. All next executions of this function cause value to be incremented by one. The function returns a reference to a constant value. This means that other functions can use the value (from afar) as if it was a variable (without having to dereference a pointer).
In my thinking, a pointer is used for an optional parameter or object. A reference is passed when the object must exist. Inside the function, a referenced parameter means that the value exists, however a pointer must be checked for null before dereferencing it. Also, with a reference, there is more guarantee that the target object is valid. A pointer could point to an invalid address (not null) and cause undefined behavior.
Semantically, references do act as addresses. However, syntactically, they are the compiler's job, not yours, and you can treat a reference as if it is the original object it points to, including binding other references to it and having them refer to the original object too. Say goodbye to pointer arithmetic in this case.
The downside of that is that you can't modify what they refer to - they are bound at construct time.