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.
Related
void ChangeValueByReference(int &x)
{
x = 0;
}
int main()
{
int a = 1;
ChangeValueByReference(a);
cout << a;
}
Why don't we put ChangeValueByReference(&a); when calling that function in main()?
Because while defining the function, we said that we will be passing a pointer void ChangeValueByReference(int &x){...}
That's because the ampersand has two different meanings, when used in different places (declaration / statement).
void MyFn(Type & a);
Here & serves as "a reference to" modifier.
Type * pA = &a;
Here & serves as "get a pointer of" operator. Notice that if you have variable a of type Type, &a returns Type * (a pointer to Type).
Compiler automatically gets a reference to variable, when you pass it to the function. So you can simply call:
ChangeValueByReference(someVariable);
And compiler will know, that it has to get a reference to someVariable.
We did not say that we'll be passing a pointer. We said that we will give a reference. A reference to a variable might internally be handled like a pointer but it is no pointer. A pointer can be 0 - a reference not.
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.
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.
}
Does dereferencing a pointer and passing that to a function which takes its argument by reference create a copy of the object?
In this case the value at the pointer is copied (though this is not necessarily the case as the optimiser may optimise it out).
int val = *pPtr;
In this case however no copy will take place:
int& rVal = *pPtr;
The reason no copy takes place is because a reference is not a machine code level construct. It is a higher level construct and thus is something the compiler uses internally rather than generating specific code for it.
The same, obviously, goes for function parameters.
In the simple case, no. There are more complicated cases, though:
void foo(float const& arg);
int * p = new int(7);
foo(*p);
Here, a temporary object is created, because the type of the dereferenced pointer (int) does not match the base type of the function parameter (float). A conversion sequence exists, and the converted temporary can be bound to arg since that's a const reference.
Hopefully it does not : it would if the called function takes its argument by value.
Furthermore, that's the expected behavior of a reference :
void inc(int &i) { ++i; }
int main()
{
int i = 0;
int *j = &i;
inc(*j);
std::cout << i << std::endl;
}
This code is expected to print 1 because inc takes its argument by reference. Had a copy been made upon inc call, the code would print 0.
No. A reference is more or less just like a pointer with different notation and the restriction that there is no null reference. But like a pointer it contains just the address of an object.
I have implemented operations on a list, one of them is add, and since i don't want to return anything, i read that i had to use **, and it works, but i saw on another place that it is passed as *&, but i don't know the difference
addNode( node *&head, int value)
addNode(node **head, int value)
What is the difference, and which one is better, or do they mean the same?
I know the second is pointer to a pointer.
Thanks
The first (**) is a pointer to a pointer and the second (*&) is a reference to a pointer.
A reference and a pointer are conceptually quite similar. But there are some important differences, for example:
A reference cannot be NULL (but it can refer to a pointer which points to NULL).
You can't modify a reference to refer to something else.
You need to dereference a pointer to access the value.
See this related question for more differences:
Difference between pointer variable and reference variable in C++
With:
addNode( node *&head, int value)
...the type of head is "reference to pointer-to-node".
With:
addNode(node **head, int value)
... the type is "pointer-to-pointer-to-node".
A pointer and a reference are not the same thing. A simple way to think of a reference is as a dereferenced pointer.
You would need different syntax to call both versions:
node* my_node = 0;
addNode(my_node, 0); // syntax for first version
addNode(&my_node, 0); // syntax for 2nd version
There are semantic differences as well. When you pass a pointer, you can pass NULL. When you pass a reference, you can't. This being a function that takes a ref-to-ptr confuses the matter a little, so let's change the problem a bit:
void make_string(string& str_ref)
{
str_ref = "my str";
}
void make_string_again(string* str_ptr)
{
*str_ptr = "my other string";
}
These two finctions do the same thing but one takes a string reference while the other takes a string pointer. If you were to do this:
string str;
make_string(str); // OK
make_string_again(&str); // OK - &str is a pointer to a real string
make_string_again(0); // Not OK - compiles but will crash when function dereferences the null pointer
You can see it becomes difficult (but not impossible) to call make_string with a null pointer. This could help you to implement better functions in the case where you expect that make_string will never be called with an invalid object.
This is the difference between pass by value and pass by reference. Pass by reference, basically, implicitly does the reference and dereference that the double pointer gets you.