Reference Declaration in C++
C++ allows
reference declarations so you can create aliases for variables.
These declarations are typically of the form:
type&
identifier =
variable
Reference declarations declare the identifier to be an alternative name, or alias, for a variable specified in an initialization of the reference. In effect, reference declarations produce lvalues:
- On the right side of an assignment expression, an lvalue is automatically dereferenced.
- On the left side, it specifies where an appropriate value is to be stored.
Passing and returning values from functions can be expensive, especially when these values are large aggregates and require copying.
Using reference declarations can avoid this overhead. Multiple assignment expressions ordinarily require the creation of temporaries to perform them.
By using reference return types, this can be managed efficiently. For ADTs, we must define such expressions unless satisfactory defaults are available.
C++ Reference
It can be easier to understand complicated pointer or
reference declarations if you read them from right to left.
A reference is a synonym for an object or function. A reference is declared just like a pointer, but with an ampersand (&) instead of an asterisk (*).
A 1) local or 2) global reference declaration must have an initializer that specifies the target of the reference. Data members and function parameters, however, do not have initializers.
You cannot declare
- a reference of a reference,
- a reference to a class member,
- a pointer to a reference,
- an array of references, or
- a cv-qualified reference.
For example:
int x;
int &r = x; // Reference to int
int& const rc = x; // Error: no cv qualified references
int & &rr; // Error: no reference of reference
int& ra[10]; // Error: no arrays of reference
int &* rp = &r; // Error: no pointer to reference
int* p = &x; // Pointer to int
int *& pr = p; // OK: reference to pointer
A reference, unlike a pointer, cannot be made to refer to a different object at runtime. Assignments to a reference are just like assignments to the referenced object.
Because a reference cannot have cv-qualifiers, there is no such thing as a const reference.
Instead, a reference to const is often called a const reference for the sake of brevity.
References are often used to bind names to temporary objects, implement call-byreference for function parameters, and optimize call-by-value for large function parameters.
The divide function in Figure 1 demonstrates the first two uses.
The standard library has the div function, which divides two integers and returns the quotienttient and remainder in a struct. Instead of copying the structure to a local object, divide binds the return value to a reference to const,
thereby avoiding an unnecessary copy of the return value. Furthermore, suppose that you would rather have divide return the results as arguments.
The function parameters quotient and rem
are references; when the divide function is called, they are bound to the function arguments, q and r, in main.
When divide assigns to quotient, it actually stores the value in q, so when divide returns, main has the quotient and remainder.
Figure 1. Returning results in function arguments
#include <cstdlib>
#include <iostream>
#include <ostream>
void divide(long num, long den, long& quotient, long& rem){
const std::ldiv_t& result = std::div(num, den);
quotient = result.quotient;
rem = result.rem;
}
int main( ){
long q, r;
divide(42, 5, q, r);
std::cout << q << " remainder " << r << '\n';
}