First code:
int a = 1;
void func(int* ptr) {
ptr = &a;
}
int main() {
int nvar = 2;
int* pvar = &nvar;
func(pvar);
std::cout << *pvar;
}
//Output: 2
Second code:
int a = 1;
void func(int*& ptr) {
ptr = &a;
}
int main() {
int nvar = 2;
int* pvar = &nvar;
func(pvar);
std::cout << *pvar;
}
//Output: 1
The only difference is the '&' character in the 'func' function. But can someone explain me, what it does in this situation?
I know what it does, but in the second code it is combined with * , and I dont know what this combination means
T& denotes "reference to T".
Now replace T with whatever you like. Eg for pointer to int, T==int* we have int*& which is a reference to a pointer to int.
It is no different to passing non-pointers to functions as references. When ptr is passed by value then func works on a copy, when passed by reference func works on the instance passed in.
The & signifies passing by reference:
The difference between pass-by-reference and pass-by-value is that modifications made to arguments passed in by reference in the called function have effect in the calling function, whereas modifications made to arguments passed in by value in the called function can not affect the calling function. Use pass-by-reference if you want to modify the argument value in the calling function. Otherwise, use pass-by-value to pass arguments.
I think that says it better than I could.
Related
I am currently taking a data structures and algorithms class and my professor gave us material that included functions that take in pointer values and pointer/reference values.
These functions would look like this:
int function1(int a); // Pass by value
int function2(int &ref); // Pass by reference
int function3(int* ptr); // This will take in a pointer value
int function4(int*& ptr); // This will take in a pointer/reference value
I understand the difference between pass by value, and pass by reference. I also have tried implementing both of the latter two examples as basic functions, but I am not entirely sure how these two arguments differ from pass by reference or how they differ from each other.
Could somebody explain how these two functions parameters work and how they could be used practically?
[...] but I am not entirely sure how these two arguments differ from
pass by reference or how they differ from each other.
In the first function
int function3(int* ptr);
// ^^^^
you pass the pointer to an int by value. Meaning int* by value.
In second one,
int function4(int*& ptr);
// ^^ --> here
you pass the pointer to the int by reference. Meaning you are passing the reference to the int* type.
But how does passing the pointer by value and by reference differ in
usage from passing a regular variable type such as an integer by value
or reference?
Same. When you pass the pointer by value, the changes that you do the passed pointer(ex: assiging another pointer) will be only valid in the function scop. On the otherside, pointer pass by reference case, you can directly make changes to the pointer in the main(). For example, see the folloiwng demonstration.
#include <iostream>
// some integer
int valueGlobal{ 200 };
void ptrByValue(int* ptrInt)
{
std::cout << "ptrByValue()\n";
ptrInt = &valueGlobal;
std::cout << "Inside function pointee: " << *ptrInt << "\n";
}
void ptrByRef(int *& ptrInt)
{
std::cout << "ptrByRef()\n";
ptrInt = &valueGlobal;
std::cout << "Inside function pointee: " << *ptrInt << "\n";
}
int main()
{
{
std::cout << "Pointer pass by value\n";
int value{ 1 };
int* ptrInt{ &value };
std::cout << "In main() pointee before function call: " << *ptrInt << "\n";
ptrByValue(ptrInt);
std::cout << "In main() pointee after function call: " << *ptrInt << "\n\n";
}
{
std::cout << "Pointer pass by reference\n";
int value{ 1 };
int* ptrInt{ &value };
std::cout << "In main() pointee before function call: " << *ptrInt << "\n";
ptrByRef(ptrInt);
std::cout << "In main() pointee after function call: " << *ptrInt << "\n\n";
}
}
Output:
Pointer pass by value
In main() pointee before function call: 1
ptrByValue()
Inside function pointee: 200
In main() pointee after function call: 1
Pointer pass by reference
In main() pointee before function call: 1
ptrByRef()
Inside function pointee: 200
In main() pointee after function call: 200
Passing a pointer by reference allow you to change the pointer and not only the pointed value. So if you do and assignment of pointer in the function int function4(int*& ptr) in this way :
ptr = nullptr;
the caller have the pointer set to "nullptr".
In the function int function3(int* ptr) the pointer passed is copied in the variabile ptr that is valid only in the scope of function3. In this case you can only change the value pointed by the pointer and not the pointer ( or to better specify you can change the pointer but only in the scope of the function ). So the previous expression ptr = nullptr; has no effect in the caller.
If you want to modify an outside int value, use this:
int function1(int* ptr) {
*ptr = 100; // Now the outside value is 100
ptr = nullptr; // Useless. This does not affect the outside pointer
}
If you want to modify an outside int* pointer, i.e. redirect that pointer, use this:
int function2(int*& ptr) {
ptr = nullptr; // Now the outside pointer is nullptr
}
Or this:
int function3(int** ptr) {
*ptr = nullptr; // Same
}
The first and second are pass by value and reference respectively as commented in the code.
The third one takes an integer pointer as a parameter by value, which can be assigned a memory location but the value of the pointer only changes locally inside the function scope.
The fourth one holds the value of an integer variable with reference as there is an amperson(&) for referencing the value(which is a pointer).
They are function declarations, not definitions so unless they are defined with a function body you can't explore its practical uses. (or a list of endless possibilities from what you could do with an integer value)
If you want a case of pass by value vs pass by reference, the classic example would be the swapping of two or more values within a function (without returning values), wherein pass by reference works and pass by value fails or your first and third functions would change the values locally inside the function only whereas the second and fourth ones would change the value in its entirety.
Is it possible to pass a single array element by reference (so that the argument passed in is modified)?
For example, say this is a main part:
int ar[5] = {1,2,3,4,5};
test(&ar[2]);
And now this is the function definition:
void test(int &p)
{
p = p + 10;
return;
}
The above code results in a compilation error.
&ar[2] takes the address of the element at the 3rd position in the array. So you try to pass an int* to an function expecting an int&. Typically you don't need to do anything to an expression to make it be treated as a reference, since a reference is just another name for some object that exists elsewhere. (This causes the confusion, since it sometimes seems to behave like a pointer).
Just pass ar[2], the object itself:
test(ar[2]);
Maybe it will be clearer if you put the array to one side for a moment, and just use an int.
void test (int &p);
// ...
int a = 54321;
test(a); // just pass a, not a pointer to a
Just to provide an alternative to BobTFish's answer. In case you need to pass an address, then your function definition needs to accept a pointer as an argument.
void test(int *arg);
// ...
int arg = 1234;
test(&arg);
and to use the address of an array element you do the following:
void test(int *arg);
// ...
int arg[0] = 1234;
test(&arg[0]);
Some people add parenthesis to the array element: &(arg[0]), which is fine when in doubt, But the [] operator has higher precedence than the & operator.
If I have a function which takes a pointer to an integer, and I pass a reference to an integer variable from my main, is this call by value or call by reference? Sample code:
#include <iostream>
using namespace std;
void fun(int *a){
//Code block
}
int main(){
int a = 5;
fun(&a);
return 0;
}
In the above code, is the call to function fun a call by value or call by reference?
Your call is a pass by value, but of type int* not of argument type int. This means that a copy of the pointer is made and passed to the function. You can change the value of what it points to but not of the pointer.
So if your function is like this
void fun(int *a)
{
*a = 10;
}
and you call from main like this
int main() {
int b = 1;
fun(&b);
// now b = 10;
return 0;
}
you could modify the value of b by passing a pointer to it to your function.
The same effect would be if you did the following - which is passing by reference
void fun2(int& a)
{
a = 5;
}
int main()
{
int b = 10;
fun2(b);
// now b = 5;
return 0;
}
Now consider a third function that takes an integer argument by value
void fun3(int a)
{
a = 10;
}
int main()
{
int b = 1;
fun3(b);
// b is still 1 now!
return 0;
}
With pass by value, fun3 changes the copy of the argument passed to it, not the variable b in the scope of main.
Passing by (non-const) reference or pointer allows the modification of the argument that is passed to it. Passing by value or const reference will not allow the argument passed to it to be changed.
You're passing a pointer to a, by value.
Depending on which level of abstraction you are speaking, you could say that you are therefore passing a by pointer, or passing a by "handle". In broader terms, "passing a by reference" would not be strictly incorrect, but it is incorrect in C++ because "reference" means something specific in C++. You have no C++ references in this code.
You are passing by value the address where a is located.
So when in your void called fun you type *a, you're accessing the value of a.
But as I've said, you're passing by value an int pointer to a.
It is call by reference as you are passing reference the address reference to your variable so,
inside function
*a = 100;
changes the value of a in caller function as the content at that address has been changed.
But address is passed by value so
a = NULL;
will not change a, as a still be pointing to same address.
What return and variable type would I need to use to catch the return value of the address of a variable passed into a function?
Say:
RETURNTYPE get_address(int num){
return #
}
int main(){
int num = 1;
DATATYPE = get_address(num);
return 0;
}
RETURNTYPE and DATATYPE should be int*, but note that it does not make much sense to return a pointer to a function argument.
Function argument exists only for as long as the function is executing. Once the function returns that variable no longer exists and using the address returned is essentially undefined behavior.
If you want address of the variable used as argument at the call site then you don't need the function get_address() at all, just use the & operator:
int main(){
int num = 1;
int* pnum = #
return 0;
}
If you have access to C++11, you can use the built-in std::addressof.
You can implement a generic function that returns the address of the parameter as such:
template<typename T>
T* addr(T& param)
{
return (T*)&(char&)param;
}
(this is the C++11 implementation, and it's like this because the unary & can be overloaded)
Note that you must pass the parameter by reference otherwise you're returning the address of a local variable, which can result in undefined behavior.
Or you can simply use &. :)
I just need to verify that the address on num is different inside and outside of the function when passed by value.
You can pass the same parameter by value and by reference:
void compareAddresses(int passedByValue, int& passedByReference)
{
std::cout << &passedByValue << " " << &passedByReference;
}
pointer is variable that holds an address. So you need pointer to int.
int* get_address (int num) {
return #
}
int main () {
int num = 1;
int* pointer = get_address(num);
return 0;
}
This above of course won't work because you pass the value by copy, and the variable will be deallocated from the stack and the pointer will be invalidated.
If you need a function you should pass it by reference (this will return the correct pointer address of the variable):
int* get_address (int &num) {
return #
}
Though you don't need a function. It's a bit excessive. That works just fine:
int* pointer = #
You can't, or rather I should say you shouldn't return the address of local scoped variables, as they no longer exist after the function returns. Therefore, you're getting only garbage.
int num = 1;
int* addr = #
In C++11 you can use auto when you don't know the type, but you cannot return auto from a function.
auto num = 1;
auto addr = #
The local variable gets destroyed after the function has finished. The function call might get over written by other function calls. You wont get what you want. So you shouldn't return a pointer to the local variable of a function.
In a C++ function like this:
int& getNumber();
what does the & mean? Is it different from:
int getNumber();
It's different.
int g_test = 0;
int& getNumberReference()
{
return g_test;
}
int getNumberValue()
{
return g_test;
}
int main()
{
int& n = getNumberReference();
int m = getNumberValue();
n = 10;
cout << g_test << endl; // prints 10
g_test = 0;
m = 10;
cout << g_test << endl; // prints 0
return 0;
}
the getNumberReference() returns a reference, under the hood it's like a pointer that points to an integer variable. Any change applyed to the reference applies to the returned variable.
The getNumberReference() is also a left-value, therefore it can be used like this:
getNumberReference() = 10;
Yes, the int& version returns a reference to an int. The int version returns an int by value.
See the section on references in the C++ FAQ
Yes, it's different.
The & means you return a reference. Otherwise it will return a copy (well, sometimes the compiler optimizes it, but that's not the problem here).
An example is vector. The operator[] returns an &. This allows us to do:
my_vector[2] = 42;
That wouldn't work with a copy.
The difference is that without the & what you get back is a copy of the returned int, suitable for passing into other routines, comparing to stuff, or copying into your own variable.
With the &, what you get back is essentially the variable containing the returned integer. That means you can actually put it on the left-hand side of an assignment, like so:
getNumber() = 200;
The first version allows you to write getNumber() = 42, which is probably not what you want. Returning references is very useful when overloading operator[] for your own containers types. It enables you to write container[9] = 42.
int& getNumber(): function returns an integer by reference.
int getNumber(): function returns an integer by value.
They differ in some ways and one of the interesting differences being that the 1st type can be used on the left side of assignment which is not possible with the 2nd type.
Example:
int global = 1;
int& getNumber() {
return global; // return global by reference.
}
int main() {
cout<<"before "<<global<<endl;
getNumber() = 2; // assign 2 to the return value which is reference.
cout<<"after "<<global<<endl;
return 0;
}
Ouptput:
before 1
after 2
"&" means reference, in this case "reference to an int".
It means that it is a reference type. What's a reference?
Wikipedia:
In the C++ programming language, a reference is a simple reference datatype that is less powerful but safer than the pointer type inherited from C. The name C++ reference may cause confusion, as in computer science a reference is a general concept datatype, with pointers and C++ references being specific reference datatype implementations. The declaration of the form:
Type & Name
where is a type and is
an identifier whose type is reference
to .
Examples:
int A = 5;
int& rA = A;
extern int& rB;
int& foo ();
void bar (int& rP);
class MyClass { int& m_b; /* ... */ };
int funcX() { return 42 ; }; int (&xFunc)() = funcX;
Here, rA and rB are of type "reference
to int", foo() is a function that
returns a reference to int, bar() is a
function with a reference parameter,
which is reference to int, MyClass is
a class with a member which is
reference to int, funcX() is a
function that returns an int, xFunc()
is an alias for funcX.
Rest of the explanation is here
It's a reference
It means it's returning a reference to an int, not an int itself.
It's a reference, which is exactly like a pointer except you don't have to use a pointer-dereference operator (* or ->) with it, the pointer dereferencing is implied.
Especially note that all the lifetime concerns (such as don't return a stack variable by address) still need to be addressed just as if a pointer was used.