Por que as referências raramente são usadas no PHP?


26

Eu tenho algum conhecimento em C ++ e sei que os ponteiros são comumente usados ​​lá, mas comecei a examinar o código-fonte aberto do PHP e nunca vejo o código usando referências nos métodos.

Em vez disso, o código sempre usa um valor de retorno em vez de passar a referência à variável para o método, que então altera o valor dessa variável e apenas o retorna.

Eu li que o uso de referências usa menos memória, então por que elas não são usadas no PHP?


19
O uso de parâmetros de passagem por referência é "programação de efeitos colaterais" - o uso de uma função para retornar um único valor é significativamente mais claro ao ler o código. Dito isto, várias funções principais do PHP usam referências.
halfer 28/02

3
O PHP passa objetos por referência por padrão.

2
tipos de matriz são um exanmple privilegiada de funções PHP núcleo que passam por referência
Mark Baker

2
As referências ao PHP não são indicadoras, e muitas vezes são um pé no saco, se você não as espera totalmente onde elas aparecem.
28713 lanzz

2
Se você precisar de vários retornos, return array($foo, $bar);elist($A, $B) = foobar();
Izkata 28/02

Respostas:


49

Sua afirmação de que as referências raramente são usadas está incorreta. Como outros já mencionaram, existem inúmeras funções nativas que usam referências, exemplos notáveis ​​incluem as funções de classificação de array e preg_match()/ preg_match_all(). Se você estiver usando alguma dessas funções no seu código, também estará usando referências.

Continuando, referências em PHP não são ponteiros. Como você é proveniente de um background em C ++, posso entender a confusão, mas as referências ao PHP são uma fera totalmente diferente, são alias de uma tabela de símbolos . Quaisquer ganhos de desempenho que você possa esperar de referências C ++ simplesmente não se aplicam a referências PHP.

De fato, na maioria dos cenários, a passagem por valor é mais rápida e consome menos memória do que a passagem por referência. O Zend Engine, o núcleo do PHP, usa um mecanismo de otimização de cópia na gravação que não cria uma cópia de uma variável até que ela seja modificada. A passagem por referência geralmente quebra o padrão de cópia na gravação e requer uma cópia, independentemente de você modificar ou não o valor.

Não tenha medo de usar referências em PHP quando precisar, mas não faça isso apenas como uma tentativa de otimizar. Lembre-se, a otimização prematura é a raiz de todo mal .

Leitura adicional:


Obrigado pela correção @NikiC. Pouco de uma resposta preguiçoso este ...
yannis

Para completar a resposta, seria bom ressaltar que todos os objetos são passados ​​por referência em PHP.
Florian Margaine 02/03

@FlorianMargaine Isso não é totalmente preciso (veja o segundo link em outras leituras).
yannis

2
@FlorianMargaine Não, os dois são muito diferentes e é importante perceber por que isso acontece.
Phant0m

3
@FlorianMargaine Não, suponha que os objetos fossem passados ​​por referência no PHP: f($obj)dado function f($x) { $x = new X; }, teriam se $objreferido a um objeto diferente do que antes da chamada para f(). No entanto, como os objetos não são passados ​​por referência, $ obj não será modificado se você o executar com PHP. Dessa forma, o PHP faz o mesmo que Java.
Phant0m

8

O PHP já faz uma coisa de copiar na gravação em que não cria um novo valor até você mudar alguma coisa, então não há muita memória salva usando referências. Fazer isso pode até mexer com algumas coisas que o PHP faz internamente para reduzir o uso de memória, tornando as coisas ainda piores.

Acrescente a isso o fato de que as referências tornam as coisas um pouco demais em geral. O padrão, e, portanto, o que a maioria das pessoas espera, é passar por valor; quando passo $ipara uma função, dificulta tremendamente as coisas ter que se preocupar se essa função muda misteriosamente $ipara algo completamente diferente e, assim, fazer cópias defensivas por precaução. (Ele já pode modificar $ise o valor é um objeto, mas, na minha opinião, não deveria.)

Basicamente, eu só gostaria de encontrar passagem por referência útil para "fora" parâmetros, ou seja, as variáveis i esperar para voltar a partir da função, em vez de passar em um la preg_match's &$matches. Mesmo para funções que modificam claramente o objeto que está sendo passado, como sortou array_pop, isso parece um pouco nojento ... mas é com isso que estamos presos.


5

PHP é uma linguagem orientada para a web.
As páginas da Web são veiculadas rapidamente e devem ser leves.
O programa PHP usual vive uma fração de segundo e consome algumas centenas de kilobytes de memória.
Não há uso para essas otimizações.


1
Este. Não precisa de ponteiros / referências, pois não está interferindo em um nível tão baixo como o C ++.
27413 Kenneth Worden

8
Por que este post recebe 5+ ??? Ele a) não responder à pergunta b) não está correto

1
Portanto, as referências são lentas e consomem muita memória?
Rocket Hazmat

1
@RocketHazmat Sim, estranhamente isso é verdade.
precisa

3

Algumas razões em tempo real:

  • O PHP é uma linguagem de script e não tem como objetivo ser usado como um software incorporado (basicamente, a memória é limpa no final do script),
  • Desde o PHP5, a passagem por referência está implícita nos parâmetros do objeto (então o PHP usa a passagem por referência "nas suas costas").

1
Veja: php.net/manual/en/language.oop5.references.php para o seu segundo ponto.
precisa

2

Eu acho que isso é apenas uma escolha dos desenvolvedores, nada a ver com a linguagem. Muitos códigos PHP (embutidos e não) usam referências. Dê uma olhada nas funções da matriz no PHP, muitas delas usam referências. preg_matchusa referências.

Eu acho que uma das razões pelas quais os desenvolvedores optam por não usar referências é porque pode ser confuso. Você chama uma função e uma das variáveis ​​pode (ou não) ser atualizada porque era uma referência. Portanto, quando você depura, pode não estar claro por que o valor de $xjsut mudou magicamente.


1

O problema fundamental da sua pergunta é que você assume que isso também é comum em C ++. Não é. Não gostamos de parâmetros de saída e os usamos o menos possível - eles são realmente muito comuns em APIs no estilo C.


0

Eu conheço muitas funções php que fazem isso. Dê uma olhada, preg_match()por exemplo. $matchesserá passado por referência

Se você deseja escrever uma função que aceita argumentos por referência, use a seguinte sintaxe

function byref(&$a, &$b, $c) {
    $a += $c;
    $b += $c;
    return $a * $b;
}

$ ae $ b são passados ​​pela referência $ c são passados ​​pelo valor.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.