1) Lorsqu'un tableau est passé en argument à une méthode ou une fonction, est-il passé par référence ou par valeur?
2) Lors de l'affectation d'un tableau à une variable, la nouvelle variable est-elle une référence au tableau d'origine ou s'agit-il d'une nouvelle copie?
Et si vous faisiez ça:
$a = array(1,2,3);
$b = $a;
Est $b
une référence à $a
?
Réponses:
Pour la deuxième partie de votre question, consultez la page du tableau du manuel , qui indique (citation) :
Et l'exemple donné:
Pour la première partie, le meilleur moyen d'en être sûr est d'essayer ;-)
Considérez cet exemple de code:
Cela donnera cette sortie:
Ce qui indique que la fonction n'a pas modifié le tableau "extérieur" qui a été passé en paramètre: il est passé en copie et non en référence.
Si vous voulez qu'il soit passé par référence, vous devrez modifier la fonction de cette façon:
Et la sortie deviendra:
Comme, cette fois, le tableau a été passé "par référence".
N'hésitez pas à lire la section Références expliquées du manuel: il devrait répondre à certaines de vos questions ;-)
la source
&
, oui, cela devrait - voir php.net/manual/en/…En ce qui concerne votre première question, le tableau est passé par référence SAUF s'il est modifié dans la méthode / fonction que vous appelez. Si vous essayez de modifier le tableau dans la méthode / fonction, une copie de celui-ci est effectuée en premier, puis seule la copie est modifiée. Cela donne l'impression que le tableau est passé par valeur alors qu'en réalité il ne l'est pas.
Par exemple, dans ce premier cas, même si vous ne définissez pas votre fonction pour accepter $ my_array par référence (en utilisant le caractère & dans la définition du paramètre), elle est toujours passée par référence (c'est-à-dire: vous ne perdez pas de mémoire avec une copie inutile).
Cependant, si vous modifiez le tableau, une copie est effectuée en premier (qui utilise plus de mémoire mais ne modifie pas votre tableau d'origine).
FYI - ceci est connu comme "copie paresseuse" ou "copie sur écriture".
la source
TL; DR
a) la méthode / fonction lit uniquement l'argument tableau => référence implicite (interne)
b) la méthode / fonction modifie l'argument tableau => valeur
c) l'argument méthode / fonction tableau est explicitement marqué comme référence (avec une esperluette) => référence explicite (user-land)
Ou ceci:
- paramètre de tableau non-esperluette : passé par référence; les opérations d'écriture modifient une nouvelle copie du tableau, copie qui est créée lors de la première écriture;
- paramètre de tableau esperluette : transmis par référence; les opérations d'écriture modifient le tableau d'origine.
N'oubliez pas - PHP effectue une copie de valeur au moment où vous écrivez dans le paramètre du tableau non esperluette. Voilà ce que ça
copy-on-write
veut dire. J'adorerais vous montrer la source C de ce comportement, mais c'est effrayant là-dedans. Mieux vaut utiliser xdebug_debug_zval () .Pascal MARTIN avait raison. Kosta Kontos l'était encore plus.
Répondre
Ça dépend.
Version longue
Je pense que je l'écris pour moi. Je devrais avoir un blog ou quelque chose ...
Chaque fois que les gens parlent de références (ou de pointeurs, d'ailleurs), ils se retrouvent généralement dans une logomachie (il suffit de regarder ce fil !).
PHP étant un langage vénérable, j'ai pensé que je devrais ajouter à la confusion (même si c'est un résumé des réponses ci-dessus). Parce que, même si deux personnes peuvent avoir raison en même temps, il vaut mieux se casser la tête en une seule réponse.
Tout d'abord, vous devez savoir que vous n'êtes pas un pédant si vous ne répondez pas en noir et blanc . Les choses sont plus compliquées que «oui / non».
Comme vous le verrez, la chose entière par valeur / par référence est très liée à ce que vous faites exactement avec ce tableau dans la portée de votre méthode / fonction: le lire ou le modifier?
Que dit PHP? (alias "en termes de changement")
Le manuel dit ceci (soulignement le mien):
Pour autant que je sache, lorsque de gros programmeurs sérieux et honnêtes envers Dieu parlent de références, ils parlent généralement de modifier la valeur de cette référence . Et c'est exactement ce que les pourparlers manuels sur:
hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.Il y a un autre cas qu'ils ne mentionnent pas: que se passe-t-il si je ne change rien - lisez simplement?
Que se passe-t-il si vous passez un tableau à une méthode qui ne marque pas explicitement une référence et que nous ne changeons pas ce tableau dans la portée de la fonction? Par exemple:
Continuez à lire, mon compagnon de voyage.
Que fait réellement PHP? (aka "mémoire-sage")
Les mêmes programmeurs gros et sérieux, quand ils deviennent encore plus sérieux, ils parlent d '"optimisations de mémoire" en ce qui concerne les références. PHP aussi. Parce
PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
que c'est pour ça .Il ne serait pas idéal de passer des tableaux HUGE à diverses fonctions, et PHP pour en faire des copies (c'est ce que fait "pass-by-value", après tout):
Eh bien maintenant, si c'était réellement une valeur de passage, nous aurions perdu 3 Mo de RAM, car il y a deux copies de ce tableau, non?
Faux. Tant que nous ne changeons pas la
$arr
variable, c'est une référence, en termes de mémoire . Vous ne le voyez tout simplement pas. C'est pourquoi PHP mentionne les références utilisateur-terre lors de la discussion&$someVar
, pour distinguer les références internes et explicites (avec esperluette).Les faits
Alors,
when an array is passed as an argument to a method or function is it passed by reference?
J'ai trouvé trois (ouais, trois) cas:
a) la méthode / fonction lit uniquement l'argument tableau
b) la méthode / fonction modifie l'argument tableau
c) l' argument méthode / fonction tableau est explicitement marqué comme référence (avec un esperluette)
Tout d'abord, voyons combien de mémoire ce tableau consomme réellement (exécutez ici ):
Que de nombreux octets. Génial.
a) la méthode / fonction lit uniquement l'argument tableau
Faisons maintenant une fonction qui ne lit que ledit tableau comme argument et nous verrons combien de mémoire la logique de lecture prend:
Tu veux deviner? J'en ai 80! Voyez par vous-même . C'est la partie que le manuel PHP omet. Si le
$arr
paramètre était réellement passé par valeur, vous verriez quelque chose de similaire aux1331840
octets. Il semble que cela$arr
se comporte comme une référence, n'est-ce pas? C'est parce qu'il est une référence - un interne.b) la méthode / fonction modifie l'argument tableau
Maintenant, écrivons à ce paramètre, au lieu de le lire:
Encore une fois, voyez par vous - même , mais, pour moi, c'est assez proche de 1331840. Donc, dans ce cas, le tableau est en fait copié
$arr
.c) l'argument tableau méthode / fonction est explicitement marqué comme référence (avec une esperluette)
Voyons maintenant combien de mémoire prend une opération d'écriture sur une référence explicite (exécutez ici ) - notez l'esperluette dans la signature de la fonction:
Je parie que vous obtenez 200 max! Cela consomme donc autant de mémoire que la lecture d'un paramètre non-esperluette .
la source
Par défaut
Les tableaux d'objets sont transmis par valeur (le tableau) mais chaque objet est transmis par référence.
Remarque: En tant qu'optimisation, chaque valeur unique est transmise comme référence jusqu'à sa modification à l'intérieur de la fonction. S'il est modifié et que la valeur a été transmise par référence, il est copié et la copie est modifiée.
la source
Lorsqu'un tableau est passé à une méthode ou une fonction en PHP, il est passé par valeur à moins que vous ne le passiez explicitement par référence, comme ceci:
Dans votre deuxième question, ce
$b
n'est pas une référence à$a
, mais une copie de$a
.Tout comme le premier exemple, vous pouvez faire référence
$a
en procédant comme suit:la source
Ce fil est un peu plus ancien mais voici quelque chose que je viens de rencontrer:
Essayez ce code:
http://codepad.viper-7.com/gwPYMw
Notez qu'il n'y a pas d'ampli pour le paramètre $ params et qu'il change toujours la valeur de $ arr ['date']. Cela ne correspond pas vraiment à toutes les autres explications ici et à ce que je pensais jusqu'à présent.
Si je clone l'objet $ params ['date'], la 2ème date sortie reste la même. Si je le mets juste sur une chaîne, cela n'affecte pas non plus la sortie.
la source
Pour étendre l'une des réponses, les sous-tableaux de tableaux multidimensionnels sont également passés par valeur, sauf s'ils sont passés explicitement par référence.
Le résultat est:
la source
En PHP, les tableaux sont passés aux fonctions par valeur par défaut, sauf si vous les passez explicitement par référence, comme le montre l'extrait de code suivant:
Voici la sortie:
la source