2012-07-19 14 views
5

Eventuali duplicati:
In PHP can someone explain cloning vs pointer reference?Se gli oggetti vengono passati da un alias quando si passa per riferimento?

Secondo http://php.net/manual/en/language.oop5.references.php

Uno dei punti chiave di PHP 5 OOP che viene spesso menzionato è che "gli oggetti sono passati per riferimenti per impostazione predefinita ". Questo non è completamente vero. Questa sezione rettifica quel pensiero generale usando alcuni esempi.

Un riferimento PHP è un alias, che consente a due variabili diverse di scrivere sullo stesso valore. A partire da PHP 5, una variabile oggetto non contiene più l'oggetto stesso come valore. Contiene solo un identificatore di oggetto che consente agli oggetti di accesso di trovare l'oggetto reale. Quando un oggetto viene inviato per argomento, restituito o assegnato a un'altra variabile, le diverse variabili non sono alias: contengono una copia dell'identificatore, che punta allo stesso oggetto.

Se gli oggetti vengono passati da alias o gestore, in quale situazione si vorrebbe effettivamente passare per riferimento?

myFunc($obj); // Pass by alias/handler 

myFunc(& $obj); // Pass by reference (when would you do this?) 

myFunc(clone $obj); // Create a new object 

Quali sono i diversi casi d'uso per ciascuno di questi?

+2

Penso che questa lezione riguardasse l'argomento: http://www.youtube.com/watch?v=bxxIXPc9IR8 (tra le altre cose) –

+2

Nota, il riferimento pass-by-call è stato deprecato almeno dal 5.3, se non prima. La funzione dichiara quali argomenti si aspetta siano riferimenti e il chiamante non deve specificare che sono riferimenti e, in effetti, non dovrebbe. – cHao

risposta

2

Quali sono i diversi casi d'uso per ciascuno di questi?

È già nominato i tre diversi casi d'uso:

  1. passaggio di un oggetto come parametro di
  2. Passando un alias come parametro di
  3. Passare un clone di oggetto come parametro

Ovviamente fai ognuna di queste tre cose quando devi fare il caso specifico. Normalmente hai solo bisogno di 1. nel 99,9%. Tu fai l'altro 0,1% quando ne hai bisogno.

Un caso d'uso examlary (come chiesto nei commenti) per un alias di variabile come parametro come un piccolo esempio (Demo):

class VarFreezer 
{ 
    private $alias; 
    private $value; 
    public function __construct(&$object) { 
     $this->alias = &$object; 
     $this->value = $object; 
    } 
    public function restore() 
    { 
     $this->alias = $this->value; 
    } 
} 

$var = new stdClass(); 
$var->value = 'I am an object now.'; 

$freezer = new VarFreezer($var); 

$var = 'I am a string now.'; 

$freezer->restore(); 

var_dump($var); 
+0

Qualche idea su quale specifico caso d'uso sarebbe per 'myFunc (& $ obj)'? –

+0

Questo è specificamente il passaggio di un alias variabile come parametro. Quindi puoi fare riferimento alla stessa variabile con un secondo nome. – hakre

+0

@Dev Sto chiedendo in modo specifico gli oggetti e il loro comportamento quando vengono passati in funzioni - non primitive come stringhe. –

2

Quando si dà un oggetto a un metodo il riferimento alla già esistente gli oggetti vengono passati in modo da avere la variabile nell'ambito di chiamata e la variabile di parametro del metodo nello scope del metodo che fa riferimento allo stesso oggetto.

È possibile utilizzare in modo esplicito & per fornire un riferimento a una primitiva come una matrice, in modo che un metodo richiamato possa modificare i dati della matrice originale. Per gli oggetti questo è il default al giorno d'oggi come hai detto.

Un clone sembra ovvio.

Con & $ obj si crea un alias in $ obj non un riferimento all'oggetto a cui si riferisce $ obj. Citando php.net:

$c = new A; 
$d = &$c; 
$c->foo = 2; 
$c = NULL; 
echo $d->foo."\n"; // Notice: Trying to get property of non-object... 
2

myfunc ($ obj) // passano in identificatore

Infatti, quando la funzione ha bisogno di ottenere l'accesso all'oggetto e manipolare/leggere da esso in qualche modo.

myfunc (& $ obj) // passare il riferimento all'identificatore.

La chiave qui è che si passa un riferimento all'identificatore. Il che significa che se la variabile esterna ($ obj) è impostata su null, anche l'oggetto interno diventa nullo perché hai rimosso l'identificativo da $ obj e quindi anche il riferimento ad esso è stato rimosso. A differenza di quando si passa l'identificatore perché ciò che effettivamente si sta facendo passando in una copia dell'identificatore e quindi se $ obj è stato impostato su null, il valore all'interno della funzione puntava ancora sull'oggetto.

esempio:

var x = new Object(); 

var y = x //y and x both contain **different** identifiers to the same object in memory. 

function a($_a){} // a function for examples 

a($y) // passes in a copy of $y so $_a (inside the function) is a third identifier pointing to th in memory object 

a(& $y) // now $_a contains the **same** identifier as $y so if either is emptied then the other is also emptied. 

a(clone $y) //creates a new object identical to the first and passes in an identifier of the new object. 

questo è la speranza abbastanza chiaro.

si passerebbe un identificatore per riferimento se si desidera essere in grado di modificare o eliminare l'identificativo dall'interno della funzione e farlo influenzare la variabile identificatore esterno pur essendo in grado di restituire un valore calcolato in modo indipendente. Ad esempio, serializzare un oggetto, salvarlo in un file restituisce la stringa di file, ma anche cancellare l'identificatore in modo che l'oggetto possa essere cancellato dalla memoria.

Problemi correlati