Historically there are languages with parameter passing by address (FORTRAN, PASCAL), and by value (PASCAL vith var keyword, C). The formal just uses equivalent memory fields for the formal and the actual parameter, but the latter copies the value of actual parameter into a local variable in the area of the subprogram.
Parameter passing is originated in the initialization semantic in C++. There is an important difference between initialization and assignment:
int i = 3; // initialization with a value: // constructor semantic int j = i; // initialization with a variable of own type // copy constructor semantic j = i; // assignment
Parameter passing follows initialization semantic:
int i = 5; int j = 6; void f1( int x, int y) { // ... } void f2( int &x, int &y) { // ... }
f1( i, j); ==> int x = i; // creates local x and copies i to x int y = j; // creates local y and copies j to y f2( i, j); ==> int &x = i; // binds x as a new name to existing i int &y = j; // binds y as a new name to existing j
A typical usage is swap:
void swap( int &x, int &y) { int tmp = x; x = y; y = tmp; } int i = 5; int j = 6; swap( i, j); assert(i==6 && j==5);
But a reference should be bound only to a left value:
swap( i, 7); // syntax error: could not bind reference to 7 int &y = 7; swap( i, 3.14); // syntax error: conversion creates temporary int, int &y = int(3.14); // and reference could not bind to temporary const int &z1 = 7; // ok: const ref could bound to 7 const int &z2 = 3.14; // ok: const ref could bound to temporary