Thursday, November 21, 2013

Pass by Value and Pass by reference - In depth

Pass by value:

·         Variable Passed by value:
o   Value of the variable is passed as a parameter
o   The called function makes a separate copy of the passed parameter
o   Therefore, if the value is changed in the called function, it does not affect the original variable’s value
e.g.
               void f(int n) { n++;} 
 
               int main()
               {    
                       int x = 2;    
                       f(x);    
                       cout << x;  // x is still 2
               }
Here, although, function f increments the value of n, it does not affect the value of original variable x

·         Pointer passed by value:
o   Value of pointer variable is passed as a parameter
o   Called function makes another copy of pointer variable
o   Therefore, both pointers now ‘point’ to the same variable
o   New pointer can modify the value at the address pointed by the original pointer
o   But since, the pointer variables are still different, modifying the new pointer will not have any effect on the original pointer

void f(int *p) {
    *p = 5;
    p = NULL;
}
 
int main() {
    int x=2;
    int *q = &x;
    f(q);
    // here, x == 5, but q != NULL
}

Pass by reference (in the context of C++):

·         Conceptually, the actual parameter itself is passed
·         Therefore, every change made in the called function affects the originally passed parameter
·         How to remember –
o   Passed just like value
o   But received as an address with &
·         Useful when function is required to calculate multiple values

e.g.

void f(int &n) { n++;}
 
int main() {
    int x = 2;
    f(x);
    cout << x; 
}
 
//Here, the output of program will be 3.
 
/*Example swap function:*/
 
void swap( int &j, int &k ) {
    int tmp = j;
    j = k;
    j = tmp;
}


Pass by constant reference (in the context of C++):

·         Same as pass by reference above, but the pointer parameter is ‘received’ and interpreted by the called function as a constant pointer. And therefore, cannot modify the contents of the original parameter passed
·         Then why not just pass by value?
o   Because some parameters, e.g. a list might be too large to pass as a parameter and therefore it makes more sense to pass a pointer to it, but at the same time, you don’t want your function to “accidentally” modify the list
e.g.
void f(const IntList &L) {
 -- the code here cannot modify L or the compiler will complain --
}
·         The member functions like “f” above, that do not modify any data members should be declared “const”
e.g.

               void f(const IntList &L) {   L.Print(cout); }
 
        If Print were NOT defined as constant, the above line of code would cause a compile time error.
 
Because L is a const-reference parameter, it is the compiler's job to be sure that L is not modified by f (and that means that no data members of L are modified). The compiler doesn't know how the Print function is implemented; it only knows how it was declared, so if it is not declared const, it assumes the worst, and complains that function f modifies its const-reference parameter L.


Arrays as parameters:
·         In C++, arrays are ALWAYS passed as parameters, even though, they’re not declared as reference parameters in function definition.
·         This means that, any change that is made to the array in the called function, ends up modifying the original array
e.g.
void f(int A[]) {
    A[0] = 5;
}
 
int main() 
{
    int B[10];
    B[0] = 2;
    f(B);
    cout << B[0] << endl;  // the output is 5
} 



Arrays as parameters:

·         In C++, arrays are ALWAYS passed as parameters, even though, they’re not declared as reference parameters in function definition.
·         This means that, any change that is made to the array in the called function, ends up modifying the original array
e.g.
void f(int A[]) {
    A[0] = 5;
}
 
int main() {
    int B[10];
    B[0] = 2;
    f(B);
    cout << B[0] << endl;  // the output is 5
}