Harold Serrano

View Original

Understanding References in C++

A C++ Pointer is a scary concept to beginners. The idea of a Pointer is simple, but its syntax is not. For example, the asterisk symbol "*" can be used to define or to dereference a pointer; the position of the asterisk determines if the Pointer is either being defined (see line 2 below) or is dereferenced (line 3).

int main() {

    int a=3; //1. Defining a variable

    int *myPointer=&a; //2. Defining a pointer

    int b=*myPointer; //3. Dereferencing a pointer

    return 0;
}

References are friendlier alternatives to pointers with nicer syntax. With References, the C++ compiler handles all the details of dereferencing a Pointer, so you don't have to.

Reference properties

A Reference is another name for a variable, i,e., an alias. A reference is not an object; It has no storage space and no memory location. In contrast, a variable and a pointer are objects. i.e., they have storage space and a memory location. This difference gives references unique requirements, such as:

  1. You must initialize a reference to an existing object.
  2. Once initialized, it can not refer to a different object.
  3. You can not manipulate a reference as an independent entity. They are simply a different name for an existing object.

Reference in action

When used in a declaration statement, the ampersand symbol "&" initializes a reference. For example, the code snippet below initializes the reference 'myReference' to the variable 'myVariable.' (see line 2)

int main(){

    int myVariable=3; //1. Defining a variable

    int &myReference=myVariable; //2. Declearing a reference and initializing it to myVariable

    return 0;
}

If you modify the value of 'myVariable,' the reference's value also changes. Remember, a reference is simply another name for a variable. The code snippet below shows this property.

In the snippet below, we modify the 'myVariable' value to 5 (line 3).

Lines 4 and 5 prints the value of 'myVariable' and 'myReference.' In this example, the project prints the value of 5 for the variable and reference.

int main(){

    int myVariable=3; //1. Defining a variable

    int &myReference=myVariable; //2. Declaring a reference and initializing it to myVariable

    myVariable=5; //3. Modify the variable

    std::cout<<myVariable<<std::endl; //4. Print the value of the variable

    std::cout<<myReference<<std::endl; //5. Print the value of the reference

 return 0;

 }

In the same manner, if 'myReference' changes value, 'myVariable' also changes value.

So, if a reference is simply another name for an existing object, why go through the trouble of using them?

The answer is that references provide a simpler syntax than pointers. When using pointers, you need to deal with passing an address and dereferencing a pointer. With references, the compiler takes care of these details for you.

For example, the following code snippet uses pointers. The function's arguments is a Pointer (line 1). Inside the function's definition, you must dereference the pointer to retrieve its value (line 2). And if you want to change the value, you must dereference the pointer (line 3).

int add(int *a); //1. argument is a pointer

int add(int *a){

    int b=*a+1; //2. dereference the pointer and increment the value by 1

    *a=5; //3. modify the value of the variable

    return b; //4. return the value of b
}

In practice, the function call requires the address of the variable. See line 2 in the snippet below:

int main() {

    int myVariable=2; //1. define a variable

    int myAnswer=add(&myVariable); //2. pass the address of the variable

    return 0;

}

The same function becomes a lot cleaner with references. Take a look at the code snippet below:

int add(int &a); //1. Function arguement requires a reference

int add(int &a){

    int b=a+1; //2. No need to dereference the variable being passed

    a=5; //3. No need to use dereference when you modify the variable

    return b;

}

The function's argument is a reference instead of a pointer (line 1). Inside the function's definition, there is no need to dereference the variable being passed to the function (lines 2 & 3). With references, you treat the variable like any other variable inside the function.

In practice, the function call does not require special syntax, such as passing its address. See line 2 in the snippet below:

int main(){

    int myVariable=2; //1. Define a variable

    int myAnswer=add(myVariable); //2. pass the variable without the need to pass its address

    return 0;
}

In summary, references were created to alleviate the pain of working with Pointers. However, references are NOT pointers. They are simply aliases for existing variables or pointers.

Hope this helps