Pourquoi les références sont-elles rarement utilisées en PHP?

26

J'ai quelques connaissances en C ++ et je sais que les pointeurs y sont couramment utilisés, mais j'ai commencé à regarder le code open source PHP et je ne vois jamais de code utilisant des références dans les méthodes.

Au lieu de cela, le code utilise toujours une valeur de retour au lieu de transmettre la référence à la variable à la méthode, qui modifie ensuite la valeur de cette variable et la renvoie simplement.

J'ai lu que l'utilisation de références utilise moins de mémoire, alors pourquoi ne sont-elles pas utilisées en PHP?

Alexander Cogneau
la source
19
L'utilisation de paramètres passe-par-référence est une «programmation à effets secondaires» - l'utilisation d'une fonction pour renvoyer une valeur unique est nettement plus claire lors de la lecture du code. Cela dit, plusieurs fonctions de base PHP utilisent des références.
halfer le
3
PHP passe les objets par référence par défaut.
2
les sortes de tableaux sont un excellent exemple des fonctions PHP de base qui passent par référence
Mark Baker
2
Les références PHP ne sont pas des pointeurs, et sont souvent pénibles si vous ne vous attendez pas à ce qu'elles apparaissent.
lanzz
2
Si vous avez besoin de plusieurs retours, return array($foo, $bar);etlist($A, $B) = foobar();
Izkata

Réponses:

49

Votre affirmation selon laquelle les références sont rarement utilisées est incorrecte. Comme d'autres l'ont déjà mentionné, il existe une tonne de fonctions natives qui utilisent des références, des exemples notables incluent les fonctions de tri de tableaux et preg_match()/ preg_match_all(). Si vous utilisez l'une de ces fonctions dans votre code, vous utilisez également des références.

En passant, les références en PHP ne sont pas des pointeurs. Puisque vous venez d'un arrière-plan C ++, je peux comprendre la confusion, mais les références PHP sont une bête entièrement différente, ce sont des alias d'une table de symboles . Les gains de performances que vous attendiez des références C ++ ne s'appliquent tout simplement pas aux références PHP.

En fait, dans la plupart des scénarios, le passage par valeur est plus rapide et moins gourmand en mémoire que le passage par référence. Le moteur Zend, le noyau de PHP, utilise un mécanisme d'optimisation de copie sur écriture qui ne crée pas de copie d'une variable tant qu'elle n'est pas modifiée. Le passage par référence rompt généralement le modèle de copie sur écriture et nécessite une copie, que vous modifiiez ou non la valeur.

N'ayez pas peur d'utiliser des références en PHP quand vous en avez besoin, mais ne le faites pas simplement comme une tentative de micro-optimisation. N'oubliez pas, l' optimisation prématurée est la racine de tout mal .

Lectures complémentaires:

yannis
la source
Merci pour la correction @NikiC. Une réponse paresseuse à celle-ci ...
yannis
Pour compléter la réponse, il serait bon de souligner que tous les objets sont passés par référence en PHP.
Florian Margaine
@FlorianMargaine Ce n'est pas tout à fait exact (voir le deuxième lien dans la suite de la lecture).
yannis
2
@FlorianMargaine Non, les deux sont très différents et il est important de comprendre pourquoi.
phant0m
3
@FlorianMargaine Non, supposons que les objets aient été passés par référence en PHP: f($obj)étant donné function f($x) { $x = new X; }, aurait fait $objréférence à un objet différent qu'avant l'appel à f(). Cependant, comme les objets ne sont pas passés par référence, $ obj n'est pas modifié si vous l'exécutez avec PHP. De cette façon, PHP fait la même chose que Java.
phant0m
8

PHP fait déjà une chose de copie sur écriture où il ne crée pas de nouvelle valeur jusqu'à ce que vous changiez quelque chose, donc il n'y a pas beaucoup de mémoire économisée en utilisant des références. Cela peut même perturber certaines choses que PHP fait en interne pour réduire l'utilisation de la mémoire, ce qui aggrave encore les choses.

Ajoutez à cela le fait que les références rendent les choses un peu trop magiques en général. La valeur par défaut, et donc ce que la plupart des gens attendent, est la valeur de passage; quand je passe $ià une fonction, cela complique énormément les choses de devoir se soucier si cette fonction change mystérieusement $ien quelque chose d'autre, et donc de faire des copies défensives au cas où. (Il peut déjà modifier $isi la valeur est un objet, mais à mon avis, il ne devrait pas.)

Fondamentalement, je ne trouverais que le passage par référence utile pour les paramètres de "sortie", ce qui signifie que les variables que je m'attends à récupérer de la fonction plutôt que de passer, a la preg_match's &$matches. Même pour les fonctions qui modifient clairement l'objet passé, comme sortou array_pop, cela semble un peu capricieux ... mais c'est ce avec quoi nous sommes coincés.

cHao
la source
5

PHP est un langage orienté web.
Les pages Web sont servies rapidement et doivent être légères.
Le programme PHP habituel vit fraction de seconde et consomme quelques centaines de kilo-octets de mémoire.
Il n'y a aucune utilité pour de telles optimisations.

Votre bon sens
la source
1
Cette. N'a pas besoin de pointeurs / références, car il ne dérange pas à un niveau aussi bas que C ++.
Kenneth Worden
8
Pourquoi ce message obtient 5+ ??? Il a) ne répond pas à la question b) n'est pas correct
1
Les références sont donc lentes et consomment trop de mémoire?
Rocket Hazmat
1
@RocketHazmat Oui, assez étrangement, c'est vrai.
yannis
3

Quelques raisons à la volée:

  • PHP est un langage de script, et ne vise pas à être utilisé comme un logiciel embarqué de base (fondamentalement, la mémoire est effacée à la fin du script),
  • Depuis PHP5, le passage par référence est implicite pour les paramètres d'objet (donc PHP utilise le passage par référence "dans votre dos").
AlterPHP
la source
1
Voir: php.net/manual/en/language.oop5.references.php pour votre deuxième point.
yannis
2

Je pense que ce n'est qu'un choix des développeurs, rien à voir avec le langage. Beaucoup de code PHP (intégré et non) utilise des références. Jetez un oeil aux fonctions de tableau en PHP, beaucoup d'entre elles utilisent des références. preg_matchutilise des références.

Je pense que l'une des raisons pour lesquelles les développeurs choisissent de ne pas utiliser de références est parce que cela peut être source de confusion. Vous appelez une fonction et l'une des variables peut (ou non) être mise à jour car il s'agissait d'une référence. Ainsi, lorsque vous déboguez, il peut ne pas être clair pourquoi la valeur de $xjsut a changé comme par magie.

Rocket Hazmat
la source
1

Le problème fondamental de votre question est que vous supposez que cela est également courant en C ++. Ce n'est pas le cas. Nous n'aimons pas les paramètres de sortie et les utilisons le moins possible - ils ne sont vraiment courants que dans les API de style C.

DeadMG
la source
0

Je connais de nombreuses fonctions php qui le font. Jetez un œil preg_match()par exemple. $matchessera transmis par référence

Si vous voulez écrire une fonction qui prend des arguments par référence, utilisez la syntaxe suivante

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

$ a et $ b sont passés par référence $ c est passé par valeur.

hek2mgl
la source