La llamada por valor y la llamada por referencia son técnicas de implementación que se confundieron con los modos de paso de parámetros hace mucho tiempo.
Al principio, estaba FORTRAN. FORTRAN solo tenía llamada por referencia, ya que las subrutinas tenían que poder modificar sus parámetros, y los ciclos de computación eran demasiado caros para permitir múltiples modos de paso de parámetros, además no se sabía lo suficiente sobre la programación cuando se definió por primera vez FORTRAN.
A ALGOL se le ocurrió llamar por nombre y llamar por valor. La llamada por valor era para cosas que no debían cambiarse (parámetros de entrada). La llamada por nombre era para los parámetros de salida. Call-by-name resultó ser un gran problema, y ALGOL 68 lo dejó caer.
PASCAL proporcionó llamada por valor y llamada por referencia. No proporcionó ninguna forma para que el programador le dijera al compilador que estaba pasando un objeto grande (generalmente una matriz) por referencia, para evitar volar la pila de parámetros, pero que el objeto no debería cambiarse.
PASCAL agregó punteros al léxico del diseño del lenguaje.
C proporcionó una llamada por valor y una llamada por referencia simulada definiendo un operador kludge para devolver un puntero a un objeto arbitrario en la memoria.
Los lenguajes posteriores copiaron C, principalmente porque los diseñadores nunca habían visto nada más. Esta es probablemente la razón por la cual la llamada por valor es tan popular.
C ++ agregó un kludge encima del C kludge para proporcionar una llamada por referencia.
Ahora, como resultado directo de call-by-value vs. call-by-reference vs. call-by-pointer-kludge, C y C ++ (programadores) tienen dolores de cabeza horribles con punteros constantes y punteros const (solo lectura) objetos.
Ada logró evitar toda esta pesadilla.
Ada no tiene una llamada explícita por valor frente a una llamada por referencia. Por el contrario, Ada tiene parámetros de entrada (que pueden leerse pero no escritos), parámetros de salida (que DEBEN escribirse antes de que puedan leerse) y parámetros de salida, que pueden leerse y escribirse en cualquier orden. El compilador decide si un parámetro en particular se pasa por valor o por referencia: es transparente para el programador.
void acceptEntireProgrammingLanguageByValue(C++);