Chamada por valor e chamada por referência são técnicas de implementação que foram confundidas com os modos de passagem de parâmetros há muito tempo.
No começo, havia FORTRAN. O FORTRAN só tinha chamada por referência, uma vez que as sub-rotinas precisavam modificar seus parâmetros, e os ciclos de computação eram muito caros para permitir vários modos de passagem de parâmetros, e não se sabia o suficiente sobre programação quando o FORTRAN foi definido pela primeira vez.
ALGOL surgiu com chamada por nome e chamada por valor. Chamada por valor era para coisas que não deveriam ser alteradas (parâmetros de entrada). Chamada por nome era para parâmetros de saída. A chamada por nome acabou por ser um grande problema, e o ALGOL 68 a abandonou.
A PASCAL forneceu chamada por valor e chamada por referência. Não foi possível ao programador dizer ao compilador que estava passando um objeto grande (geralmente uma matriz) por referência, para evitar explodir a pilha de parâmetros, mas que o objeto não deve ser alterado.
PASCAL adicionou ponteiros ao léxico do design de idiomas.
C forneceu chamada por valor e simulação por chamada, definindo um operador kludge para retornar um ponteiro para um objeto arbitrário na memória.
Os idiomas posteriores copiaram C, principalmente porque os designers nunca haviam visto mais nada. É provavelmente por isso que a chamada por valor é tão popular.
O C ++ adicionou um kludge em cima do C kludge para fornecer chamada por referência.
Agora, como resultado direto de chamada por valor vs. chamada por referência vs. chamada por ponteiro kludge, C e C ++ (programadores) têm dores de cabeça horríveis com ponteiros const e ponteiros para const (somente leitura) objetos.
Ada conseguiu evitar todo esse pesadelo.
O Ada não possui chamada explícita por valor x chamada por referência. Em vez disso, Ada possui parâmetros (que podem ser lidos, mas não escritos), parâmetros de saída (que DEVEM ser escritos antes que possam ser lidos) e parâmetros de saída, que podem ser lidos e escritos em qualquer ordem. O compilador decide se um parâmetro específico é passado por valor ou por referência: é transparente para o programador.
void acceptEntireProgrammingLanguageByValue(C++);