Page 1 sur 1

nom de variables, foreach et &

Posté : 16 mars 2009, 23:17
par niahoo
bonjour, j'ai trouvé sur le forum de commentçamarche un truc bizZzare, peut-être pourrez vous m'éclairer:

vous remarquerez que dans le foreach, la varaible $v est parfois écrite &$v

ça vient du code que le forumeur avait posté, il utilisait deux foreach sans instructions dans les accolades, l'un avec et l'un sans le &

Code : Tout sélectionner

<?php $a = array('zero', 'one' , 'two'); foreach($a as $v){ echo $v; echo "<br />"; } print_r($a); echo "<br />"; foreach($a as &$v){ echo $v; echo "<br />"; } print_r($a); echo "<br />"; ?>
donne :
zero
one
two
Array ( [0] => zero [1] => one [2] => two )
zero
one
two
Array ( [0] => zero [1] => one [2] => two )

et

Code : Tout sélectionner

<?php $a = array('zero', 'one' , 'two'); foreach($a as &$v){ echo $v; echo "<br />"; } print_r($a); echo "<br />"; foreach($a as $v){ echo $v; echo "<br />"; } print_r($a); echo "<br />"; ?>
donne :
zero
one
two
Array ( [0] => zero [1] => one [2] => two )
zero
one
one
Array ( [0] => zero [1] => one [2] => one )



donc la troisieme variable n'est détruite que quand je place la varaible avec le & en premier, mai selle n'est détruite que quand on l'utilise sans le '&'


pourriez vous m'éclairer sur l'utilisation de ce '&', je flaire le truc utile mais aussi le bug.


voici le topic original:

http://www.commentcamarche.net/forum/ed ... 7361&cat=3


merci à tous

Posté : 17 mars 2009, 08:44
par naholyr
Le '&' signifie un passage par référence et pas par copie, mais c'est un peu plus "puissant" qu'un pointeur classique dans les autres langages.

Illustration :
$variable = 5; // variabel = 5
$copie = $variable; // copie = 5
$reference = &$variable; // reference = 5
$copie = 6; // copie = 6, variable = 5 (inchangé)
$reference = 7; // reference = 7, variable = 7 (modifié par référence), copie = 6 (inchangé)
C'est le même fonctionnement dans foreach
foreach ($array as &$v) {
  $v = 1;
}
est équivalent à
foreach ($array as $k => $v) {
  $array[$k] = 1;
}
Et c'est bien un comportement volontaire et souhaité de foreach, introduit en PHP 5.je-sais-plus-combien.

Posté : 17 mars 2009, 12:24
par julian
Pour compléter ce qu'à dis naholyr, ce qu'il faut voir c'est la distinction entre :
foreach ($array as &$v) {
  $v = 1;
}
et
foreach ($array as $v) {
  $v = 1;
}
Dans le second cas, le variable $v est une copie (à un autre endroit de la mémoire) de la valeur de l'élément du tableau $array, tandis que dans le premier cas, $v contient une référence à l'endroit où est enregistré la valeur de l'élément du tableau.
Le problème dans le second cas, c'est qu'on ne peut faire qu'une opération de lecture, mais pas d'écriture, car c'est la copie de la variable qui sera modifiée...

Posté : 17 mars 2009, 18:43
par AB
Pour faire une opération d'écriture je préfère de loin la seconde syntaxe indiquée par naholyr
foreach ($array as &$v) {
  $v = 1;
}
est équivalent à
foreach ($array as $k => $v) {
  $array[$k] = 1;
}
Et c'est bien un comportement volontaire et souhaité de foreach, introduit en PHP 5.je-sais-plus-combien.
car passer la valeur par référence peut facilement être source de bug :
<?php
$a = array(0 => 0, 1 => 1, 2 => 2);

foreach ($a as &$v) {
  $v = $v + 1;
} 

print_r($a);

$v = 'autre';

print_r($a);
?>

Posté : 17 mars 2009, 21:33
par niahoo
Bon, j'avoue ne pas vraiment piger pourquoi les deux dernières valeurs du tableau sont toujours identiques.. mais vu que c'est pas souvent qu'on fait ça tant pis.

Avez-vous dans vos tiroirs un script ou l'utilisation des références est utile en PHP ?

merci.

Posté : 17 mars 2009, 23:48
par savageman
Pour compléter ce qu'à dis naholyr, ce qu'il faut voir c'est la distinction entre :
foreach ($array as &$v) {
  $v = 1;
}
et
foreach ($array as $v) {
  $v = 1;
}
Dans le second cas, le variable $v est une copie (à un autre endroit de la mémoire) de la valeur de l'élément du tableau $array, tandis que dans le premier cas, $v contient une référence à l'endroit où est enregistré la valeur de l'élément du tableau.
Le problème dans le second cas, c'est qu'on ne peut faire qu'une opération de lecture, mais pas d'écriture, car c'est la copie de la variable qui sera modifiée...
En fait, PHP est assez intelligent et tant que tu n'écris pas de valeur dans le tableau, il ne le copies pas ! :D
Dans le cas du premier post - faire un echo dans le foreach() - les deux scripts sont donc strictement identiques niveau performances ou consommation mémoire. ;)