School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 307,096 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 2,035 people online right now. Registration is fast and FREE... Join Now!




Passing By Reference

 
Reply to this topicStart new topic

> Passing By Reference, A Comparison Among Languages

KYA
Group Icon



post 7 Mar, 2009 - 08:14 PM
Post #1


Passing By Reference

At some point, I imagine you have had the need for functions to communicate with one another. It usually takes the form of function parameters since global variables are not good programming practice. A basic version looks like:

CODE

void function (int theNum)
{
   //do stuff with the num
}
int main()
{
   int a = 5;
   function(a);
  return 0;
}


There are two ways to pass a parameter and the distinguishing between them is very important; it can create bugs and make or break your program in some instances. First let's consider C++. C++, by default has parameters passed as shallow copies of whatever they are supposed to be. consider the following snippet:

CODE

void function (int theNum)
{
    theNum = 6;
}
int main()
{
   int a = 5;
   function(a);
   cout << a << endl;
  return 0;
}


What do you expect the output to be? 6? Nope, a shallow copy of the 'a' integer was passed to the function. This copy's value was modified to 6, but as soon as the function returns it goes out of scope and 'a' remains the same. This is where references and pointers come in handy. Consider this snippet:

CODE

void function(int& theNum)
{
    theNum = 6;
}
int main()
{
    int a = 5;
        cout << a << endl;
    function(a);
    cout << a << endl;
    return 0;
}


When we pass 'a' from main to the function, a copy is not passed, we pass the reference to 'a' to the function. This allows us to modify the value of a directly. This is both powerful and dangerous since (unless we are careful) we can accidentally modify a value and have a tough bug to find. The output of this snippet is 5, 6, indicating we successfully modified a's value. We can achieve the same effect with pointers (which are more often used then references since they have more abilities, but that goes out of the scope of what I'm talking about in this tutorial). Consider this:

CODE

void function(int* theNum)
{
    *theNum = 6;
}
int main()
{
    int a = 5;
    cout << a << endl;
    function(&a);
    cout << a << endl;
    return 0;
}


We pass a reference to a as the param in main, this is assigned to the pointer "theNum" in function and then we assign the value of theNum (its derefernece location to 6). The output is the same as the previous snippet: 5, 6. Effectively two ways to reach the same destination. The ability to expressly use pointers and references is an advantage (and both a curse?) C++ has over java. Consider a typical swap function:

CODE

void swap(int* first, int* second)
{
    int temp = *first;
    *first = *second;
    *second = temp;
}
int main()
{
    int a = 5, b = 6;
    cout << a << " " << b << endl;
    swap(&a, &b);
    cout << a << " " << b << endl;
    return 0;
}


We create two integers, pass their references and "swap" their values using a temp holder. This is only possibly by using pointers. If we tried the exact same concept with java it would fail. Consider the same snippet in java:

CODE

    public static void swap (int first, int second)
    {
        int temp = first;
        first = second;
        second = temp;
    }
    public static void main (String args[])
    {
    
        int a = 5, b = 6;
        System.out.println(a + " " + b);
        swap (a,b);
        System.out.println(a + " " + b);
    
    }


The output is 5,6 5,6. Why? Because we did not pass the reference to the numbers (in this instance it was a shallow copy). This can get confusing since java handles objects as reference, but method parameters by value. "Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value." The scope of the parameters end with the death of the function.

In short: If the argument is a primitive type, then it is passed by value. If the argument is an object (or an array), then it "can be" considered pass-by-reference. However, java does not pass by reference--at all.

Java does not allow programmers to directly access and play around with object pointers. To protect us I suppose, but it requires a little extra effort on our part to solve the problem. If the numbers are a part of a data structure and we pass the structure as well, then any assignments will remain in effect, even after the death of the function:

CODE

    public static void swap (int[] arr)
    {
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1]= temp;
    }
    public static void main (String args[])
    {
    
        int[] nums = {5,6};
        System.out.println(nums[0] + " " + nums[1]);
        swap (nums);
        System.out.println(nums[0] + " " + nums[1]);
    
    }


The array is passed as an object reference [by value] (remember that an array has an implicit pointer to the first element in C++ which we can access and it also exists in java, but we cannot manipulate it the same way, i.e. directly). You can change an object reference's values and such, but you cannot change what it points at. Sidenote: the subscript operator [] is the same as dereferencing the pointer + the element you want to access in C++:

CODE

//Neat little thing to know
arr[3] == *(arr + 3);


For a final look-see, I'll show you two string permutation algorithms, one in C++ and the other in Java. Both work, however, see if you can notice the difference needed to make it work in java:

CODE

//C++
#include <iostream>
#include <string>
using namespace std;

void swap(char* first, char* second)
{
        char ch = *second;
        *second = *first;
        *first = ch;
}

int permute(char* set, int begin, int end)
{
        int i;
        int range = end - begin;
        if (range == 1) {
                cout << set << endl;
        } else {
                for(i=0; i<range; i++) {
                        swap(&set[begin], &set[begin+i]);        //initial swap
                        permute(set, begin+1, end);            //recursion
                        swap(&set[begin], &set[begin+i]);       //swap back
                }
        }
        return 0;
}

//Example Implementation -- Up to you on how to use
int main()
{
        char str[255]; //string
    cout << "Please enter a string: ";
    cin.getline(str, 255); //take string
        permute(str, 0, strlen(str)); //permutate the string
        return 0;
}


VS.

CODE

//java
import java.io.*;

public class Permute {
    
    public static void swap(char[] set, int first, int second)
    {
            char ch = set[second];
            set[second] = set[first]; //swap the values
            set[first] = ch;
    }
    
    public static int permute(char[] set, int begin, int end)
    {
            int i;
            int range = end - begin;
            if (range == 1) {
                    System.out.println(set); //print out each permutation
            } else {
                    for(i=0; i<range; i++) {
                            swap(set, begin, begin+i);        //initial swap
                            permute(set, begin+1, end);        //recursion
                            swap(set, begin, begin+i);       //swap back
                    }
            }
            return 0;
    }

    //***************TEST EXAMPLE********************
    public static void main(String[] args) {
        
        char[] test = {'a','b','c','d'};;
        permute(test, 0, 4);
    }

}



Found it? The answer is, in java I had to pass the array so the swapping would be permanent, otherwise it wouldn't display the permutations correctly; it would be as if the swap never happened. Specifically here:

CODE

public static void swap(char[] set, int first, int second) {}

//versus

void swap(char* first, char* second)


As with most programming endeavors, there are many routes to solve a problem. It is knowing how best to utilize your tools at your disposal that makes you a good programmer. In the above work, one way is not necessarily better then the other, as it would be comparing apples to oranges. Each has a different manner in which things must be handled. Hopefully you found this both useful and interesting. Happy coding!

--KYA
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!


Fast ReplyReply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 11/21/09 11:52AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month