Altri suggerimenti

Per quanto riguarda la prima domanda, l'array viene passato per riferimento meno che non venga modificato all'interno del metodo / funzione che si sta chiamando. Se si tenta di modificare la matrice all'interno del metodo / funzione, una copia è fatta prima, e quindi solo la copia viene modificato. Questo fa sembrare come se l'array viene passato per valore, quando in realtà non lo è.

Ad esempio, in questo primo caso, anche se non sta definendo la funzione di accettare $ my_array per riferimento (utilizzando il carattere & nella definizione dei parametri), esso viene comunque passato per riferimento (vale a dire: si don' t memoria dei rifiuti con una copia non necessaria).

function handle_array($my_array) {  

    // ... read from but do not modify $my_array
    print_r($my_array);

    // ... $my_array effectively passed by reference since no copy is made
}

Tuttavia, se si modifica la matrice, una copia di esso è fatto prima (che utilizza più memoria, ma lascia la matrice originale inalterato).

function handle_array($my_array) {

    // ... modify $my_array
    $my_array[] = "New value";

    // ... $my_array effectively passed by value since requires local copy
}

A proposito - questo è conosciuto come "copia pigro" o "copy-on-write"

.

TL;DR

a) il metodo/funzione si limita a leggere l'argomento dell'array => riferimento implicito (interno).
b) il metodo/funzione modifica l'argomento dell'array => valore
c) l'argomento dell'array metodo/funzione è esplicitamente contrassegnato come riferimento (con una e commerciale) => riferimento esplicito (utente-territorio).

O questo:
- parametro array non e commerciale:passato per riferimento;le operazioni di scrittura alterano una nuova copia dell'array, copia che viene creata alla prima scrittura;
- param. array e commerciale:passato per riferimento;le operazioni di scrittura alterano l'array originale.

Ricorda: PHP esegue una copia del valore nel momento in cui scrivi al parametro dell'array non e commerciale.Questo è ciò che copy-on-write significa.Mi piacerebbe mostrarti la fonte C di questo comportamento, ma è spaventoso lì dentro.Migliore utilizzo xdebug_debug_zval().

Pascal MARTIN aveva ragione.Kosta Kontos lo era ancora di più.

Risposta

Dipende.

Versione lunga

Penso che lo scriverò per me stesso.Dovrei avere un blog o qualcosa del genere...

Ogni volta che le persone parlano di riferimenti (o puntatori, del resto), di solito finiscono in una logomachia (basta guardare questo filo!).
Essendo PHP un linguaggio venerabile, ho pensato che avrei dovuto aggiungere confusione (anche se questo è un riassunto delle risposte di cui sopra).Perché, anche se due persone possono avere ragione allo stesso tempo, è meglio semplicemente sbattere le loro teste insieme in un'unica risposta.

Prima di tutto, dovresti saperlo non sei un pedante se non rispondi in bianco e nero.Le cose sono più complicate del "sì/no".

Come vedrai, l'intera questione per valore/per riferimento è molto correlata a cosa stai facendo esattamente con quell'array nell'ambito del tuo metodo/funzione:leggendolo o modificandolo?

Cosa dice PHP?(noto anche come "cambiamento")

IL Manuale dice questo (sottolineatura mia):

Per impostazione predefinita, gli argomenti della funzione sono passato per valore (in modo che se il valore dell'argomento all'interno della funzione è cambiato, non viene cambiato al di fuori della funzione).Per consentire a una funzione di modificare I suoi argomenti, devono essere passato per riferimento.

Per avere un argomento su una funzione sempre superato per riferimento, preparare un ampersand (&) al nome dell'argomento nella definizione della funzione

Per quanto ne so, quando programmatori grandi, seri e onesti parlano di riferimenti, di solito parlano di alterando il valore di quel riferimento.Ed è proprio di questo che parla il manuale: hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value".

C'è un altro caso che non menzionano, però:cosa succede se non cambio nulla, leggo solo?
Cosa succede se passi un array a un metodo che non contrassegna esplicitamente un riferimento e non modifichiamo l'array nell'ambito della funzione?Per esempio.:

<?php
function readAndDoStuffWithAnArray($array) 
{
    return $array[0] + $array[1] + $array[2];
}

$x = array(1, 2, 3);

echo readAndDoStuffWithAnArray($x);

Continua a leggere, mio ​​compagno di viaggio.

Cosa fa effettivamente PHP?(ovvero "dal punto di vista della memoria")

Gli stessi grandi e seri programmatori, quando diventano ancora più seri, parlano di "ottimizzazioni della memoria" rispetto ai riferimenti.Lo stesso vale per PHP.Perché PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting, quello è Perché.

Non sarebbe l'ideale passare array ENORMI a varie funzioni e PHP farne delle copie (dopo tutto questo è ciò che fa "pass-by-value"):

<?php

// filling an array with 10000 elements of int 1
// let's say it grabs 3 mb from your RAM
$x = array_fill(0, 10000, 1); 

// pass by value, right? RIGHT?
function readArray($arr) { // <-- a new symbol (variable) gets created here
    echo count($arr); // let's just read the array
}

readArray($x);

Bene, se questo fosse effettivamente un valore pass-by, avremmo perso almeno 3 MB di RAM, perché ci sono due copie di quell'array, giusto?

Sbagliato.Finché non cambiamo il $arr variabile, questo è un riferimento, a livello di memoria.Semplicemente non lo vedi.Ecco perché PHP menziona terreno utente Riferimenti quando si parla di &$someVar, per distinguere tra quelli interni ed espliciti (con la e commerciale).

Fatti

COSÌ, when an array is passed as an argument to a method or function is it passed by reference?

Mi è venuta in mente tre (sì, tre) casi:
a) il metodo/funzione si limita a leggere l'argomento dell'array
b) il metodo/funzione modifica l'argomento dell'array
c) l'argomento dell'array metodo/funzione è esplicitamente contrassegnato come riferimento (con una e commerciale)


Innanzitutto, vediamo quanta memoria consuma effettivamente l'array (run Qui):

<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840

Così tanti byte.Grande.

a) il metodo/funzione si limita a leggere l'argomento dell'array

Ora creiamo una funzione which si limita a leggere il suddetto array come argomento e vedremo quanta memoria occupa la logica di lettura:

<?php

function printUsedMemory($arr) 
{
    $start_memory = memory_get_usage();

    count($arr);       // read
    $x = $arr[0];      // read (+ minor assignment)
    $arr[0] - $arr[1]; // read

    echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}

$x = array_fill(0, 10000, 1); // this is 1331840 bytes
printUsedMemory($x);

Vuoi indovinare?ne ho 80! Guarda tu stesso.Questa è la parte che il manuale PHP omette.Se la $arr param fosse effettivamente passato per valore, vedresti qualcosa di simile a 1331840 byte.Sembra che $arr si comporta come un riferimento, vero?Questo è perché È un riferimento - uno interno.

b) il metodo/funzione modifica l'argomento dell'array

Ora facciamo scrivere a quel parametro, invece di leggerlo:

<?php

function printUsedMemory($arr)
{
    $start_memory = memory_get_usage();

    $arr[0] = 1; // WRITE!

    echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}

$x = array_fill(0, 10000, 1);
printUsedMemory($x);

Ancora, vedere di persona, ma per me è abbastanza vicino a 1331840.Quindi, in questo caso, l'array È effettivamente copiato $arr.

c) l'argomento dell'array metodo/funzione è esplicitamente contrassegnato come riferimento (con una e commerciale)

Ora vediamo quanta memoria un'operazione di scrittura su un riferimento esplicito prende (corri Qui) - notare la e commerciale nella firma della funzione:

<?php

function printUsedMemory(&$arr) // <----- explicit, user-land, pass-by-reference
{
    $start_memory = memory_get_usage();

    $arr[0] = 1; // WRITE!

    echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}

$x = array_fill(0, 10000, 1);
printUsedMemory($x);

La mia scommessa è che otterrai un massimo di 200!Quindi questo consuma all'incirca la stessa quantità di memoria di leggendo da un parametro diverso da e commerciale.

Per impostazione predefinita

  1. Le primitive vengono passate per valore.Diversamente da Java, in PHP la stringa è primitiva
  2. Gli array di primitive vengono passati per valore
  3. Gli oggetti vengono passati riferimento
  4. Gli array di oggetti vengono passati per valore (l'array) ma ogni oggetto viene passato per riferimento.

    <?php
    $obj=new stdClass();
    $obj->field='world';
    
    $original=array($obj);
    
    
    function example($hello) {
        $hello[0]->field='mundo'; // change will be applied in $original
        $hello[1]=new stdClass(); // change will not be applied in $original
        $
    }
    
    example($original);
    
    var_dump($original);
    // array(1) { [0]=> object(stdClass)#1 (1) { ["field"]=> string(5) "mundo" } } 
    

Nota:Come ottimizzazione, ogni singolo valore viene passato come riferimento finché non viene modificato all'interno della funzione.Se viene modificato e il valore è stato passato per riferimento, viene copiato e la copia viene modificata.

Quando un array viene passato a un metodo o una funzione in PHP, viene passato dal valore se non si passa esplicitamente per riferimento, in questo modo:

function test(&$array) {
    $array['new'] = 'hey';
}

$a = $array(1,2,3);
// prints [0=>1,1=>2,2=>3]
var_dump($a);
test($a);
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);

Nella tua seconda domanda, $b non è un riferimento a $a, ma una copia di $a.

Un po 'come il primo esempio, è possibile fare riferimento $a effettuando le seguenti operazioni:

$a = array(1,2,3);
$b = &$a;
// prints [0=>1,1=>2,2=>3]
var_dump($b);
$b['new'] = 'hey';
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);

Questo thread è un po 'più vecchio ma qui qualcosa che ho appena incontrato:

Prova questo codice:

$date = new DateTime();
$arr = ['date' => $date];

echo $date->format('Ymd') . '<br>';
mytest($arr);
echo $date->format('Ymd') . '<br>';

function mytest($params = []) {
    if (isset($params['date'])) {
        $params['date']->add(new DateInterval('P1D'));
    }
}

http://codepad.viper-7.com/gwPYMw

Si noti non v'è alcun amplificatore per il parametro $ params e ancora cambia il valore di $ arr [ 'data']. Questo non corrisponde realmente con tutte le altre spiegazioni qui e quello che ho pensato fino ad ora.

Se io clonare il $ params [ 'data'] oggetto, la data di uscita dei 2 ° rimane lo stesso. Se ho appena impostata a una stringa che non influenza l'uscita sia.

In array PHP sono passati alle funzioni per valore di default, a meno che non li passa in modo esplicito per riferimento, come il seguente frammento mostra:

$foo = array(11, 22, 33);

function hello($fooarg) {
  $fooarg[0] = 99;
}

function world(&$fooarg) {
  $fooarg[0] = 66;
}

hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value

world($foo);
var_dump($foo); // (original array modified) array passed-by-reference

Ecco l'output:

array(3) {
  [0]=>
  int(11)
  [1]=>
  int(22)
  [2]=>
  int(33)
}
array(3) {
  [0]=>
  int(66)
  [1]=>
  int(22)
  [2]=>
  int(33)
}

Per estendere una delle risposte, anche sottoarray di array multidimensionali sono passati per valore se non passato esplicitamente per riferimento.

<?php
$foo = array( array(1,2,3), 22, 33);

function hello($fooarg) {
  $fooarg[0][0] = 99;
}

function world(&$fooarg) {
  $fooarg[0][0] = 66;
}

hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value

world($foo);
var_dump($foo); // (original array modified) array passed-by-reference

Il risultato è:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  [1]=>
  int(22)
  [2]=>
  int(33)
}
array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(66)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  [1]=>
  int(22)
  [2]=>
  int(33)
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top