Diff Between Call By Reference And Call By Pointer [duplicate] - c++

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 9 years ago.
Can any one tell me the exact diff between call by pointer and call by reference. Actually what is happening on both case?
Eg:
Call By Reference:
void swap(int &x, int &y)
{
int temp;
temp = x; /* save the value at address x */
x = y; /* put y into x */
y = temp; /* put x into y */
return;
}
swap(a, b);
Call By Pointer:
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
swap(&a, &b);

The both cases do exactly the same.
However, the small difference is, that references are never null (and inside function you are sure, that they are referencing valid variable). On the other hand, pointers may be empty or may point to invalid place in memory, causing an AV.

Semantically these calls have identical results; under the hood references are implemented with pointers.
The important difference between using references and pointers is with references you have a lot less rope to hang yourself with. References are always pointing to "something", where as pointers can point to anything. For example, it is perfectly possible to do something like this
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
++x;
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
And now this code could do anything, crash, run, have monkeys fly out of your noes, anything.
When in doubt, prefer references. They are a higher, safer level of abstraction on pointers.

In your example, there is no difference.
In C++ reference is implemented using pointers.
Edit: for those who believe reference can't be NULL:
int calc(int &arg)
{
return arg;
}
int test(int *arg)
{
return calc(*arg);
}
Guess, what will be the result for test(0)?

Your code is C++ code. In Java there are no pointers. Both examples do the same thing, functionally there is no difference.

I don't know exactly why this was tagged jave as there are no pointers. However, for the concept you can use both pointers and reference interchangeably if you are working on the value attribute. for example i=4 or *i=4. The advantage of using pointers is that you can manipulate the adress itself. Sometimes you will need to modify the adress (point it to something else ...) this is when pointers are different for reference; pointers allow you to work directly on the adress, reference won't

Related

Why can't my function access and modify the variable passed to it?

i have written this little program to explain my point and my variable a remains unchanged it prints 4. I later learned that I need to use pointers or references; why is that?
#include <iostream>
void setToTen(int x) { x = 10; }
int main(){
int a = 4;
setToTen(a);
std::cout << a << std::endl;
}
In C++ arguments to functions are passed by value. This means that when you write
setToTen(a);
the parameter int x in setToTen is given a copy of the value stored in the variable a. In other words, you're not actually handing off the variable a into the setToTen function. Instead, you're giving a copy of that value to setToTen, so the changes made in that function affect the copy rather than the original.
On the other hand, if you change setToTen so that it takes its parameter by reference, like this:
void setToTen(int& x) {
x = 10;
}
the story is different. Here, calling setToTen(a) essentially hands the variable a into the function setToTen, rather than a copy of the value. That means that changes made to the parameter x in setToTen will change the variable a.
Your code requests a copy of x by having the signature void setToTen(int x).
Being able to take things by copy means that reasoning about the behavior of a function is far easier. This is true both for you, and for the compiler.
For example, imagine this:
int increase_some( int x, int y, int z ) {
for (int i = 0; i < y; ++i )
x+=z;
return x;
}
because x y and z are copies, you can reason about what this does. If they where references to the values "outside" of increase_some, the bit where you x+=z could change y or z and things could get crazy.
But because we know they are copies, we can say increase_some returns x if y<=0, and otherwise returns x+y*z.
Which means that the optimizer could change it to exactly that:
int increase_some( int x, int y, int z ) {
if (y<=0) return x;
return x + y*z;
}
and generate that output.
This is a toy example, but we took a complex function and turned it into a simple one. Real optimizers do this all the time with pieces of your complex function.
Going one step further, by taking things by immutable value, and never touching global state, we can treat your code as "functional", only depending on its arguments. Which means the compiler can take repeated calls to a function and reduce them to one call.
This is so valuable that compilers will transform code that doesn't have immutable copies of primitive data into code that does before trying to optimize -- this is known as static single assignment form.
In theory, a complex program with lots of functions taking things by reference could be optimized this same way, and nothing be lost. But in practice that gets hard, and it is really easy to accidentally screw it up.
That is the other side; making it easier to reason about by people.
And all you have to embrace is the idea of taking arguments by value.
Function parameters are function local variables that are not alive after exiting function.
You can imagine the function definition and its call
int a = 4;
setToTen(a);
//...
void setToTen(int x) { x = 10; }
the following way
int a = 4;
setToTen(a);
//...
void setToTen( /* int x */ ) { int x = a; x = 10; }
As it is seen within the function there is declared a local variable x which is initialized by the argument a. Any changes of the local variable x do not influence on the original argument a.
If you want to change the original variable itself you should pass it by reference that is the function will deal with a reference to the variable. For example
void setToTen(int &x) { x = 10; }
In this case you can imagine the function definition and its call the following way
int a = 4;
setToTen(a);
//...
void setToTen( /* int x */ ) { int &x = a; x = 10; }
As you see the reference x is as usual local. But it references the original argument a. In this case the argument will be changed through the local reference.
Another way is to declare the parameter as pointer. For example
void setToTen(int *x) { *x = 10; }
In this case you have to pass the original argument indirectly by its address.
int a = 4;
setToTen( &a );

Why pointer to pointer?

A very general question: I was wondering why we use pointer to pointer?
A pointer to pointer will hold the address of a pointer which in turn will point to another pointer. But, this could be achieved even by using a single pointer.
Consider the following example:
{
int number = 10;
int *a = NULL;
a = &number;
int *b = a;
int *pointer1 = NULL;
pointer1 = b; //pointer1 points to the address of number which has value 10
int **pointer2 = NULL;
pointer2 = &b; //pointer2 points to the address of b which in turn points to the address of number which has value 10. Why **pointer2??
return 0;
}
I think you answered your own question, the code is correct, what you commented isn't.
int number = 10; is the value
int *pointer1 = b; points to the address where int number is kept
int **pointer2 = &b; points to the address where address of int number is kept
Do you see the pattern here??
address = * (single indirection)
address of address = ** (double indirection)
The following expressions are true:
*pointer2 == b
**pointer2 == 10
The following is not!
*pointer2 == 10
Pointer to pointer can be useful when you want to change to what a pointer points to outside of a function. For example
void func(int** ptr)
{
*ptr = new int;
**ptr = 1337;
}
int main()
{
int* p = NULL;
func(&p);
std::cout << *p << std::endl; // writes 1337 to console
delete p;
}
A stupid example to show what can be achieved :) With just a pointer this can not be done.
First of all, a pointer doesn't point to a value. It point to a memory location (that is it contains a memory address) which in turn contains a value. So when you write
pointer1 = b;
pointer1 points to the same memory location as b which is the variable number. Now after that is you execute
pointer2 = &b;
Then pointer2 point to the memory location of b which doesn't contains 10 but the address of the variable number
Your assumption is incorrect. pointer2 does not point to the value 10, but to the (address of the) pointer b. Dereferencing pointer2 with the * operator produces an int *, not an int.
You need pointers to pointers for the same reasons you need pointers in the first place: to implement pass-by-reference parameters in function calls, to effect sharing of data between data structures, and so on.
In c such construction made sense, with bigger data structures. The OOP in C, because of lack of possibility to implement methods withing structures, the methods had c++ this parameter passed explicitly. Also some structures were defined by a pointer to one specially selected element, which was held in the scope global to the methods.
So when you wanted to pass whole stucture, E.g. a tree, and needed to change the root, or 1st element of a list, you passes a pointer-to-a-pointer to this special root/head element, so you could change it.
Note: This is c-style implementation using c++ syntax for convienience.
void add_element_to_list(List** list, Data element){
Data new_el = new Data(element); // this would be malloc and struct copy
*list = new_el; //move the address of list, so it begins at new element
}
In c++ there is reference mechanismm and you generally you can implement nearly anything with it. It basically makes usage of pointers at all obsolete it c++, at least in many, many cases. You also design objects and work on them, and everything is hidden under the hood those two.
There was also a nice question lately "Why do we use pointers in c++?" or something like that.
A simple example is an implementation of a matrix (it's an example, it's not the best way to implement matrices in C++).
int nrows = 10;
int ncols = 15;
double** M = new double*[nrows];
for(unsigned long int i = 0; i < nrows; ++i)
M[i] = new double[ncols];
M[3][7] = 3.1416;
You'll rarely see this construct in normal C++ code, since C++ has references. It's useful in C for "passing by reference:"
int allocate_something(void **p)
{
*p = malloc(whatever);
if (*p)
return 1;
else
return 0;
}
The equivalent C++ code would use void *&p for the parameter.
Still, you could imagine e.g. a resource monitor like this:
struct Resource;
struct Holder
{
Resource *res;
};
struct Monitor
{
Resource **res;
void monitor(const Holder &h) { res = &h.res; }
Resource& getResource() const { return **res; }
}
Yes, it's contrived, but the idea's there - it will keep a pointer to the pointer stored in a holder, and correctly return that resource even when the holder's res pointer changes.
Of course, it's a dangling dereference waiting to happen - normally, you'd avoid code like this.

passing variable to function with & in the header

I am doing a procedure and it's working but I'm not sure if it'll work in all cases as it's not conventional.
void func (int &num){
num=blah;
}
int main() {
int num;
func(num);
}
I know the conventional way of doing this is as below but still I have a lot of code in the previous format I prefer not to change as it works just fine. What I don't understand is whether I'm just being lucky.
void func (int* num){
*num=blah;
}
int main() {
int num;
func(&num);
}
In fact there is a bit more complicated version of it as well:
void func(float* &list){
list=new float[3];
}
int main() {
float *list;
func(list);
}
which again I understand the conventional way of doing it is as below.
void func(float** list){
*list=new float[3];
}
int main(){
float *list;
func(&list);
}
Your help is much appreciated as I'm in total confusion.
Your first example is correct - you're passing an int by reference to func().
Your second example also fine (now that you've edited it). In this case, you're passing an int * by value to func().
Your third and fourth examples are also both correct. In the third, you're passing a float * by reference. In the second case, you're passing a float ** by value (which is semantically similar to passing a float * by reference, which might be why you're confusing them).
There's nothing "conventional" or "unconventional" about any of your example code. All of it is 100% correct and will work fine. Though there are some subtle semantic differences between passing pointers by value and passing by references, these examples are ok.
The syntax with int & is not C, but C++. It is a so-called reference. If your C (not C++) compiler accepts is, then it is a non-standard extension (for a C++ compiler it's part of the language, of course).
The basic mechanics of a reference is that it acts as a name (or another name) for an existing object. For example:
int a;
int& b = a;
b = 3; /* equivalent to a = 3 */
One way to think about the reference is as an automatically dereferenced pointer (that's also how it is commonly implemented). That is, the above code is equivalent to
int a;
int* pb = &a;
*pb = 3;
The Form Func(int &x) is the c++ form of pass by reference c does not support this. It is logically equivocation of passing by a pointer. The comnplier take the address for you implicitly in the call.
In C you would allways declare
Func(int *x)
{ ... }
And call it
Func(&SomeInt);

Is it compulsory to initialize pointers in C++?

Is it compulsory to initialize t in the following code, before assigning value to t? Is the code correct?
void swap(int *x, int *y)
{
int *t;
*t = *x;
*x = *y;
*y = *t;
}
You don't need pointer to begin with:
void swap(int *x,int *y)
{
int t; //not a pointer!
t=*x;
*x=*y;
*y=t;
}
int a = 10, b = 20;
swap( &a, &b); //<-----------note : Needed &
--
Or maybe, you want the following swap function:
void swap(int & x,int & y) //parameters are references now!
{
int t; //not a pointer!
t=x;
x=y;
y=t;
}
int a = 10, b = 20;
swap(a,b); //<----------- Note: Not needed & anymore!
is the following section of code correct?
Nopes! Your code invokes Undefined behaviour because you are trying to dereference a wild pointer.
int *t;
*t=*x; // bad
Try this rather
int t; // a pointer is not needed here
t=*x;
or this
int *t = x; // initialize the pointer
That code contains undefined behavior:
int *t;
*t=*x; // where will the value be copied?
Besides that it makes no sense - you need a temporary variable to store the value, not the pointer.
int t; // not a pointer
t=*x;
*x=*y;
*y=t;
It's correct for a pointer.
Only references need to be initialized upon declaration (or in a constructor for instance members).
EDIT: but you got errors in your code, you shouldn't be dereferencing your parameters (ie int *ptr = otherPtr; is fine, not int *ptr = *otherPtr;)
If you just want to make your pointer point to already-initialized data, then you don't need to initialize it. The way you do it, though, yes, you want to use one of the malloc functions to allocate enough heap space for an integer.
The proper, efficient way, to do swapping in C/C++ is
void swap(int *x, int *y) {
int *t = x;
x = y;
y = t;
}
You can find the right way of doing this here
#include <stdio.h>
void swap(int *i, int *j)
{
int t;
t = *i;
*i = *j;
*j = t;
}
Basically the reason has been explained to you by sharptooth but there you will find some more details and explanations about what happens in background when you do such a swap. Hope it helps to clear your ideas.
int *t;
*t=*x;
t is not pointing to any valid location to be able to dereference.
is it compulsory to initialize , before assigning value to pointer t.
Yes, initializing / assigning to point to a valid memory location. Else where would it point to. It might some point to garbage and lead to undefined behavior on dereferencing.

C++ Passing Struct Address

Im a little bit confused about passing structs into functions. I understand pointers and everything.
But for instance:
struct stuff
{
int one
int two
};
int main{
stuff fnc;
fnc.two = 2;
fnc.one = 1;
multiply(&fnc);
}
void multiply(const stuff * pm){
cout << pm->one * pm->two;
}
First of all....am i even doing this right.
And second of all, why do we use the address operator when we pass the function, but use the * pointer operator in the actual function call?
Im confused?
Yes, your code is compilable other than the missing semicolons in the defintion of struct stuff. I'm not quite sure exactly what you're asking about passing the function and the actual function call, but I think you're wondering why the function call uses &fnc, but the parameter is stuff *pm? In that case, the fnc variable declared is a plain stuff. It is not a pointer, it refers to the actual instance of that struct.
Now the multiply function is declared as taking a stuff* -- a pointer to a stuff. This means that you can't pass fnc directly -- it's a stuff and multiply expects a *stuff. However, you can pass fnc as a stuff* by using the & operator to take the address, and &fnc is a valid stuff* that can be passed to multiply.
Once you're in the multiply function, you now have a stuff* called pm. To get the one and two variables from this stuff*, you use the pointer to member operator (->) since they are pointers to a stuff and not a plain stuff. After obtaining those values (pm->one and pm->two), the code then multiples them together before printing them out (pm->one * pm->two).
The * and & operands mean different things depending on whether they describe the type or describe the variable:
int x; // x is an integer
int* y = &x; // y is a pointer that stores the address of x
int& z = x; // z is a reference to x
int a = *y; // a in an integer whose value is the deference of y
Your pm variable is declared as a pointer, so the stuff type is modified with *. Your fnc variable is being used (namely for its address), and thus the variable itself is marked with &.
You can imagine the above examples as the following (C++ doesn't actually have these, so don't go looking for them):
int x;
pointer<int> y = addressof(x);
reference<int> z = x;
int a = dereference(y);
It the difference between describing a type and performing an operation.
In
void multiply(const stuff * pm){
cout << pm->one * pm->two;
}
The stuff * pm says that pm is an address of a stuff struct.
The
&fnc
says "the address of fnc".
When a variable is declared like:
stuff *pm;
it tells us that pm should be treated like an address whose underlying type is stuff.
And if we want to get the address of a variable stuff fnc, we must use
&fnc
You need the address of operator so you can get the address of the object, creating a pointer, which the function expects. The '*' in the parameter list is not a pointer operator, it simply says that the variable is a pointer.
Your code is correct. In the main, you successfully create a 'stuff' object and set its values. Then, you pass a constant address to the object into the function multiply. The multiply function then uses that address to access the two variables of the structure to output the multiplication of the variables.
The * in "const stuff * pm" means that it takes a constant pointer to a stuff object.
Here is a working example of what you would like to see.
#include <iostream>
using namespace std;
struct stuff
{
int one;
int two;
};
void multiply(stuff* pm)
{
cout << pm->one * pm->two;
}
int main()
{
stuff* fnc = new stuff;
fnc->two = 1;
fnc->one = 2;
multiply(fnc);
delete fnc;
cin.ignore(1000, 10);
return 0;
}
Sure, this would work, aside from your erroneous main function definition.
The reason why this works is because when you use the unary & operator, it essentially returns a pointer to the operand, so in your case, fnc, which is of type stuff, if you did &fnc, that would return a stuff *. This is why the multiply function must take in a stuff *.
struct stuff
{
int one, two;
};
int main(int argc, const char* argv[]) {
stuff fnc;
fnc.two = 2;
fnc.one = 1;
multiply(&fnc); //passes a pointer to fnc
}
void multiply(const stuff * pm){
//the "*" operator is the multiplication operator, not a pointer dereference
cout << pm->one * pm->two; //->one is equivalent to (*pm).one
}
You have a couple of syntactic errors in your program, but other than that, the basic idea is fine. Here are the syntax problems I had to fix before your program would compile:
#include <iostream>
using namespace std;
struct stuff
{
int one;
int two;
};
void multiply(const stuff * pm) {
cout << pm->one * pm->two;
}
int main() {
stuff fnc;
fnc.two = 2;
fnc.one = 1;
multiply(&fnc);
}
To answer your questions about difference between the '&' (address of) operator and the '*' (pointer dereference) operator though, we just need to think about the types you're passing in to the function.
Take the function multiply:
void multiply(stuff *fnc) {
...
}
In the definition of this function, you are describing something that takes a pointer to a stuff struct. In that first line, you aren't saying you are dereferencing that object, just that you are expecting a pointer to a stuff object.
Now when you call multiply:
stuff fnc;
multiply(&fnc);
You are using the '&' (address of) operator to get a pointer to the object. Since the multiply function expects a pointer, and you have the plain old object, you need to use the & operator to get a pointer to give to the multiply function.
Perhaps it is clearer to think call it like this:
stuff fnc; //The actual object
stuff* fnc_ptr = &fnc; //A pointer to a stuff object, initialized to point at fnc created above
multiply(fnc_ptr); //Call the function with the pointer directly
Following code will tell you about the pointer illustration
A struct address is passed into the function named multiply and this
function perform some operations with the element of the passed
structure and store the result in the result variable.
you can see here clearly that the result variable is previously zero then after passing the address of the structure to the function multiply the result variable value gets updated to value 6. this is how pointer works.
#include <iostream.h>
struct stuff
{
int one;
int two ;
int result;
};
void multiply(stuff *pm);
int main(){
stuff fnc;
fnc.two = 2;
fnc.one = 3;
fnc.result = 0;
multiply(&fnc);
cout<<fnc.result;
return 0;
}
void multiply(stuff *pm)
{
pm->result = pm->one * pm->two;
}