2014-10-02 10 views
8

Sto leggendo questo articolo sui riferimenti alle variabili PHP: http://derickrethans.nl/talks/phparch-php-variables-article.pdf e volevo verificare se la mia comprensione è corretta, riguardo al momento in cui vengono creati nuovi contenitori di variabili.Come funzionano i riferimenti PHP sotto controllo per gli array?

Per i non array, i contenitori variabili vengono creati ogni volta che si assegna una variabile che non punta a un contenitore con is_ref set.

Ex 1 (let {..} be a container): 
$a = 1;  // "a" => {integer, 1, is_ref = 0, ref_count = 1} 

$b = $a; // "a", "b" => {integer, 1, is_ref = 0, ref_count = 2} 

$b = 2;  // "a" => {integer, 1, is_ref = 0, ref_count = 1} 
      // "b" => {integer, 2, is_ref = 0, ref_count = 1} 

Ex 2: 
$a = 1;  // "a" => {integer, 1, is_ref = 0, ref_count = 1} 

$b = &$a; // "a", "b" => {integer, 1, is_ref = 1, ref_count = 2} 

$b = 2;  // "a", "b" => {integer, 2, is_ref = 1, ref_count = 2} 

Come funziona per gli array? Non sembra che si applichi la stessa cosa. Ad esempio,

$a = array(1, 2, 3); 
$b = $a; 
$c = &$b[2]; 
$c = 4; 
print_r($a); // prints (1, 2, 3) instead of (1, 2, 4) 
print_r($b); // prints (1, 2, 4) 

La mia aspettativa:

$ ae $ b punta allo stesso contenitore. All'interno di questo contenitore, abbiamo 3 tasti numerici "0", "1", "2" che puntano ai contenitori per gli interi 1, 2 e 3 rispettivamente.

Quando facciamo $c = &$b[2], si aggiorna il contenitore contenente intero 3:

  • is_ref = 0 diventa is_ref = 1
  • ref_count = 1 diventa ref_count = 2.

Quando facciamo $c = 4, aggiorniamo il contenitore contenente numero intero 3:

  • inte ger 3 diventa intero 4 poiché is_ref è impostato

Tuttavia, c'è qualcosa di sbagliato nella mia aspettativa perché $a[2] != 4 alla fine. Sto cercando di capire perché. La mia ipotesi migliore è che quando proviamo a fare riferimento a elementi di un array o proprietà di un oggetto, il motore PHP controlla prima l'array/oggetto stesso per vedere se is_ref = 1. Se lo è, tutto funziona secondo le mie aspettative. Se is_ref = 0, succede qualcos'altro, che è quello che sto vedendo. Qualcuno può spiegarmi cosa sia quel "qualcos'altro"?

EDIT Sembra che questo è ciò che sta realmente succedendo. Questo codice dovrebbe chiarire tutto!

$a = array(1, 2, 3); 
$b = $a; 
$c = &$b[2];  // $b points to a new container where $b[0], $b[1] still point to same container as $a[0], $a[1], but $b[2] points to a new container also pointed to by $c 
$d = $b;  // $d points to $b's container, this means changing $c will also change $d[2]  
$d[0] = 5;  // The container pointed to by $d[0] is the same as the one pointed to by $a[0] and $b[0]. Since this container has is_ref = 0, $d[0] will now point to a new container 

// At this point $a = (1, 2, 3), $b = (1, 2, 3), $c = 3, $d = (5, 2, 3) 

$d[2] = 25;  // The container pointed to by $d[2] is the same as the one pointed to by $b[2] and $c. Since this container has is_ref = 1, Changing $d[2] will affect both $b[2] and $c. 

// At this point $a = (1, 2, 3), $b = (1, 2, 25), $c = 25, $d = (5, 2, 25) 

$e = $d[2];  // Since $d[2]'s container has is_ref = 1, $e will point to its own container 

$c = 4;   // Same idea as $d[2] = 25; except $e won't get affected 

// At this point $a = (1, 2, 3), $b = (1, 2, 4), $c = 4, $d = (5, 2, 4), $e = 25 

// only way to have $d[2] be different from $b[2] is to make the container's is_ref = 0 
unset($b[2]); 
unset($c); 
$b[2] = $d[2]; 
$d[2] = 55; 

// At this point $a = (1, 2, 3), $b = (1, 2, 4), $d = (5, 2, 25), $e = 25 
+0

Non sono sicuro al 100% ma quello che penso è '$ c = 4;' definisce il numero intero 4 alla variabile. Quindi non tiene più il puntatore a '$ b [2]'. Quindi ha senso che '$ b [2]' non contenga '4'. –

+0

possibile duplicato di [PHP Reference in array key] (http://stackoverflow.com/questions/26098982/php-reference-in-array-key) –

risposta

2

cosa si è creato $a era una variabile semplice. Ma quando hai creato $b, per impostazione predefinita, PHP ha copiato la variabile. Quindi $b è completamente separato da $a, proprio come nel primo esempio.

quindi impostare $c uguale al riferimento -$b[2]. Quindi entrambi puntano allo stesso indirizzo di memoria . Aggiorna uno e aggiorna l'altro. Il problema è che pensi che $a debba essere aggiornato, ma non dovrebbe essere perché $b è la sua variabile.Considerate ciò che accade quando si cambia $b a un riferimento a $a

$a = array(1, 2, 3); 
$b = &$a; 
$c = &$b[2]; 
$c = 4; 
print_r($a); // prints (1, 2, 4) 
print_r($b); // prints (1, 2, 4) 

Questo funziona come descrivi perché $b e $a di riferimento la stessa cosa (tecnicamente $b è ora un simbolo che indica $a)

Se si desidera per immergerti ancora di più nell'argomento ecco un eccellente articolo che lo copre in profondità. http://webandphp.com/how-php-manages-variables

+0

Grazie! Questo è un articolo davvero utile. Ho aggiornato la mia domanda con quello che sta succedendo sotto il cofano. Spero di aver capito bene questa volta. – Popcorn

+0

Non preciso al 100%: '$ c = &$b[2];' è un caso speciale: fare riferimento ai valori dell'array rende effettivamente l'array anche un riferimento –

Problemi correlati