C++ Return Reference

Learn via video course
FREE
View all courses
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
Topics Covered

Overview

In C++, a reference is a copy of a variable or an alias(alternate name) given to the memory location that stores the address of the original variable and is very similar to a pointer in C++. Whenever the copy of the variable is modified, the original variable will also be modified. We can use this C++ return reference concept to retain the value of the variables and many other features which is not possible with normal return statements.

C++ Return by Reference

Introduction

A reference is represented by the ampersand symbol(&) in C++ and is an alias or copy of the original variable. A shallow copy in C++ is made to create a reference variable, which means that the reference variable points to the address of the original variable, and any changes made to the reference variable will be reflected in the original variable. For example, if b is a shallow copy of a, then if the value of b changes, then the value of a will also change because b will have the same address as a.

The following images illustrate this,

references-in-cpp

The following syntax is used to create a reference variable,

The & denotes that the variable is a reference variable and the original_var is the variable from which the reference_var is referenced. The reference variable must be initialized on declaring the variable. Therefore, the declaration int& variable; will result in an error.

The C++ return by reference concept is used to create a function that returns a reference to the original variable.

Syntax

The syntax of the function which returns a reference in C++ is,

  • The data_type& represents that the returned variable will be a reference variable of the data type data_type.
  • The data_type& original_variable represents that a reference variable named original_variable will be created to the variable passed as a parameter to the function.
  • The return original_varible will return the created reference variable and marks the end of the function.

Parameters

  • The data_type& is the return data type of the function.
  • The function_name is the name of the function.
  • The parameter of the function is the original_variable.

In the above syntax, a normal variable is passed to the function and a new reference variable or an implicit pointer to the original variable is created and returned by the function. Therefore it is important to note that the property of reference is used in both the return statement and the argument passed to the function.

Consider the following case,

Here oringinal_vaiable is a normal variable. On passing this to the function, the following occurs,

A reference variable is created and returned by the function.

Algorithm

The algorithm for the C++ return reference function is as follows,

  • Declare a function with return type and parameter as reference variables.
  • Perform the required actions with the reference variable inside the function.
  • Return the reference variable.

For example, the following piece of code declares and defines a function that returns a reference of type int,

  • Call the function with a normal variable.

For example, the following piece of code illustrates the calling of the function declared in the above code snippet,

Examples of C++ Return by Reference

Let us see different examples to understand the working of C++ return by reference,

Illustration I

The following is a basic example that utilizes the concept of incrementing a variable to understand the concept of return by reference in C++. The example also illustrates the difference between returning the reference variable itself and returning a copy of the reference variable,

Copy of reference variable

  • In the above example, the int copy_number stores the copy of the reference variable returned by the copy() function.
  • This occurs because the copy_number is declared as a normal int variable instead of a reference variable (int&).
  • This stores the copy_number in a new location of the memory and this number will be independent of the original variable.
  • Any changes made to the copy_number variable will not be reflected in the original variable.

The returned reference variable

  • The int& reference_number is declared as a reference variable and will store the reference variable returned by the copy() function.
  • When the reference_number is modified, then the original variable referenced by it will also be modified.
  • This is illustrated by incrementing the reference_number and checking the increment of the original variable.

The output for the above example is,

In the output, we can see that even when the copy number is incremented, the original number remains the same.

Illustration II

The following example illustrates the manipulation of address in functions that return a reference and also explains the concept of using a function that returns a reference on the left side of an assignment operator.

This example will collaborate with the above example to make things very clear.

Address of reference variables

  • The above example is similar to the example in the previous section and this example illustrates the change of addresses for each variable after a function call is displayed.
  • We can see that the address of variable a and the variable b are the same as b is a reference variable of a. This will not be the case for copy variables.

Calling function in LHS of operator

  • Since, the function return_by_ref() returns references to the value passed as a parameter in the function, the function can be used in the LHS of the assignment operator.
  • The value in the RHS of the assignment operator will be assigned to the returned reference which results in the change of the original variable.

The output of the above example is,

From the output, we can see that the address for the copied variable, c is different from all the other addresses which are referenced from the variable a.

Illustration III: Return by Reference using Global Variable

The C++ return reference functions are mostly used in Standard Templating libraries(STL) to perform an effective update of a variable.

The following example illustrates a program that updates values in an array using the return reference in C++,

Update a value using return reference

In the above example, the C++ return reference function is used to update the values in the array. The function call of setValues(1) is similar to original_array[1] as the function returns a reference to the setValues() function and the respective values on the right-hand side(RHS) of the assignment will be assigned to the array.

The output of the above example is,

Illustration IV: Return by Reference using Local Variable

Returning a local variable by reference in C++ is a bad practice and should never be used, as it makes the code vulnerable to security attacks.

One of the basic concepts of a program is that all the space used by the program will be freed after the execution of the program. The vulnerability in this method is that there are possibilities for leaving memory without freeing them after program execution which can be exploited.

The following program shows an example of returning a local variable by reference using C++. Please remember that these practices must never be followed,

Returning local variable

The above example illustrates how a local variable can be returned as a reference. The total concept of returning a local reference is explained on the basis of the following errors.

The reason for the error in printing the local_refernce function is explained below,

  • On calling the function, the local variable is created and returned.
  • A function call uses a stack memory to store variables and when the function is returned the stack is destroyed along with the pointer to where the space has been allocated for the local variable.
  • So trying to print the local_refernce variable, the program couldn't find the memory location of the variable.

This causes leakage in memory as the memory is allocated somewhere, but is not known to the compiler. Therefore, it is necessary to clear the allocated memory for the variable using the delete method.

The delete &new_string throws an error due to the following reason,

  • The variable new_string is a copy of the reference returned by the return_local_pointer() function.
  • Since, the variable new_string is a copy of the reference variable, its address is not allocated manually using the new or malloc keywords. Since the variable is not allocated space by the user, the space of the variable is not accessible to the user and we can't use a delete function on the variable to manually delete the space of the variable.

The following code can be used to understand the above point,

The above code is valid and will not throw any errors, as the space is manually allocated using the new operator.

The following code throws an error, as the space is allocated by the compiler and is not accessible to the user,

The const keyword can be used to make a constant reference to the variable and it is not possible to change the value of this variable. This technique is used to make reference to large classes or struct objects as a means of compiler optimization and to improve the performance of the compiler.

Another important difference in using constant reference is that the original data is not copied when passed as a parameter to a function.

A better and errorless solution to return the reference of a local variable is using unique_ptr or a unique pointer.

  • A unique pointer is a type of smart pointer that can persist longer that the timeline of the function.
  • The smart pointer acts like a container to the pointer and is used to store pointers. The unique pointer can store only one pointer.
  • These pointers can deallocate the pointers stored in them and free the space allocated to them using destructors.
  • The memory library has to be included to use the unique pointer in the code.

The following syntax is used to declare a unique pointer,

  • The data_type is the data type of the unique pointer.
  • The pointer_name denotes the name given to the unique pointer which can be later used to refer to the pointer.
  • The value is the value assigned to the unique pointer

The following program illustrates the usage of the unique pointer in resolving the problem of memory leaks in the program,

The output of the above program is,

We may wonder where the & symbol represents a reference variable. The reference variable is an implicit pointer which means that both the following functions are the same,

It's just that reference is easy to use.

Another way of handling the memory leak problem of returning a reference of local variables in C++ is to convert the local variable to a static variable. Static variables will not be destroyed after the execution of the function and have a lifetime till the end of the execution of the program. Since the static variables are not deleted and can be accessed through the program, there will be no memory leak in the program.

The output of the above program will be,

Important Points to Remember While Returning by Reference in C++

  • Unlike normal functions, values cannot be directly returned as references because a value doesn't have a fixed address to be referenced. For example, the following function results in the cannot bind non-const lvalue error,
  • Never return a local variable as a reference from a function as this makes the code vulnerable to memory leaks. This practice also makes the function abide by return value optimization(RVO), a technique in which the creation of temporary variables to hold return values is prevented.
  • The function which returns a reference can be used on both sides of the assignment operator, the program can be modeled with this point in mind as this can save space that will be required for a separate variable and is more efficient.

FAQs

Q: Why does the segmentation fault error occur while working with local references in C++?**

A: The segmentation fault error occurs when we try to access a memory location that is not manually allocated by us and is allocated directly by the compiler. The unique pointers explained in the above sections can be used to prevent this error.

  • A static variable is initialized only one time through the program. Learn more about static variables in C++.
  • A pointer is used to store an address in which a variable is present. Learn more about pointers.
  • A constant variable can't be updated after initialization. Learn more about the const keyword.

Conclusion

  • The & symbol must be used near the return type of the function to specify the function to return a reference.
  • The variable to which the result of the function is stored can be a copy of the reference to the original variable and this depends on the declaration of the variable.
  • Be careful, when handling returning a reference using local variables as they can produce memory leaks.
  • Smart pointers and static variables can be used to solve the problem of memory leaks.
  • Standard Template Libray(STL) uses a C++ return reference to update values in vectors and lists.