Outras dicas

Com relação à sua primeira pergunta, a matriz é transmitida por referência a menos que seja modificado dentro do método / função que você está chamando. Se você tentar modificar a matriz dentro do método / função, uma cópia do que é feito em primeiro lugar, e, em seguida, apenas a cópia é modificada. Isso faz parecer como se a matriz é passado por valor quando na realidade não é.

Por exemplo, neste primeiro caso, mesmo que você não está definindo sua função para aceitar $ my_array por referência (utilizando o caractere & na definição do parâmetro), ele ainda é passado por referência (ou seja: você não' t memória resíduos com uma cópia desnecessário).

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
}

No entanto, se você modificar a matriz, uma cópia do que é feito primeiro (que usa mais memória, mas deixa a sua matriz original inalterado).

function handle_array($my_array) {

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

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

FYI -. Isso é conhecido como "copy preguiçoso" ou "copy-on-write"

TL; DR

a) o método / função lê apenas o argumento de matriz => implícita referência (interno)
b) o método / função modifica o argumento array => valor
c) o argumento de matriz método / função é explicitamente marcado como uma referência (com um e comercial) => referência explícita (user-terra)

Ou este:
- não-comercial matriz param : passados ??por referência; as operações de escrita alterar uma nova cópia da matriz, exemplar, que é criado na primeira gravação;
- E comercial série param : passado por referência; as operações de escrita alterar a matriz original.

Lembre-se - PHP faz um valor-copy do momento que você escrever para o comercial não-array param. Isso é o que significa copy-on-write. Eu adoraria mostrar-lhe a fonte C deste comportamento, mas é assustador lá. Melhor utilização xdebug_debug_zval () .

Pascal MARTIN estava certo. Kosta Kontos foi ainda mais.

Resposta

Depende.

Versão longa

Eu acho que estou escrevendo isso para mim. I deve ter um blog ou algo assim ...

Sempre que as pessoas falam de referências (ou ponteiros, para que o assunto), eles geralmente acabam em um logomaquia (basta olhar para este fio !).
PHP ser uma linguagem venerável, eu pensei que eu deveria adicionar-se à confusão (embora este um resumo das respostas acima). Porque, apesar de duas pessoas pode estar certo, ao mesmo tempo, você é melhor fora apenas quebrando suas cabeças juntas em uma resposta.

Primeiro, você deve saber que você não é um pedante se você não responder de forma preto-e-branco . As coisas são mais complicadas do que "sim / não".

Como você vai ver, o todo por valor / por referência coisa está muito relacionado com o que exatamente você está fazendo com essa matriz em seu método escopo / função:? Lê-lo ou modificá-lo

O que PHP diz? (Aka "mudança-wise")

O manual do diz esta (grifo meu):

Por padrão, argumentos de função são passados ??por valor (de modo que, se o valor do parâmetro dentro da função é mudado , ele não fica alterado fora da função). Para permitir que uma função Modificar a sua argumentos, eles devem ser passado por referência .

Para ter um argumento para uma função sempre passado por referência, preceder um comercial (&) ao nome de argumento na definição da função

Tanto quanto eu posso dizer, quando grandes e graves, programadores honesto-a-Deus falar sobre referências, eles costumam falar sobre alterando o valor dessa referência . E isso é exatamente o que as negociações manuais sobre:. hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"

Há um outro caso em que eles não mencionam, no entanto: o que se eu não mudar nada - apenas ler
? E se você passar um array para um método que não explicitamente marcas de referência, e não mudarmos essa matriz no âmbito da função? Por exemplo:.

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

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

echo readAndDoStuffWithAnArray($x);

Leia, meu companheiro de viagem.

O que PHP realmente fazer? (Aka "memória-wise")

As mesmas grandes e graves programadores, quando chegar ainda mais grave, eles falam sobre "otimizações de memória" no que diz respeito às referências. O mesmo acontece com PHP. Porque PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting, isso é por .

Não seria ideal para passar matrizes enormes para várias funções, e PHP para fazer cópias deles (que é o "pass-by-value" faz, afinal de contas):

<?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);

BemAgora, se isso realmente era passagem por valor, teríamos alguns 3MB + RAM ido embora, porque há dois cópias desse array, certo?

errada. Enquanto não mudarmos a variável $arr, que é uma referência, Memória-wise . Você simplesmente não vê-lo. É por isso que PHP menciona user-terra referências quando se fala de &$someVar, para distinguir entre os internos e explícitas (com e comercial).

Factos

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

Eu vim com três (é, três) casos :
a) o método / função lê somente o argumento de matriz
b) o método / função modifica a matriz argumento
c) o argumento de matriz método / função é explicitamente marcado como uma referência (com um e comercial)


Em primeiro lugar, vamos ver a quantidade de memória que matriz realmente come (RUN aqui ):

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

Que muitas bytes. Ótimo.

a) o método / função só lê o argumento array

Agora vamos fazer uma função que só lê a referida matriz como um argumento e vamos ver a quantidade de memória a lógica de leitura leva:

<?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);

Quer adivinhar? Recebo 80! ver por si mesmo . Esta é a parte que os omite manual do PHP. Se o param $arr foi realmente passou por valor, você veria algo parecido com bytes 1331840. Parece que se comporta $arr como uma referência, não é? Isso porque ele é A referências - um interno.

b) o método / função modifica o argumento array

Agora, vamos write para que param, em vez de ler a partir dele:

<?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);

Mais uma vez, ver por si mesmo , mas, para mim, isso é muito perto de ser 1331840. Portanto, neste caso, a matriz é realmente está sendo copiado para $arr.

c) o argumento de matriz método / função é explicitamente marcado como uma referência (com um e comercial)

Agora vamos ver a quantidade de memória a operação de gravação para uma referência explícita leva (run aqui ) - observe o ampersand na assinatura da função:

<?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);

A minha aposta é que você começa 200 max! Portanto, este come aproximadamente tanta memória como leitura de um não-comercial param .

Por padrão

  1. Primitives são passados ??por valor. Não deve Java, string é primitiva em PHP
  2. matrizes de primitivos são passados ??por valor
  3. Os objetos são passados ??por referência
  4. Matrizes de objectos são passados ??por valor (matriz), mas cada objecto é passado por referência.

    <?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" } } 
    

Observação: Como uma optimização, cada valor único é passado como referência até que a sua modificada dentro da função. Se for modificado eo valor foi passado por referência, em seguida, é copiado e a cópia é modificada.

Quando uma matriz é passado para um método ou função em PHP, ele é passado por valor, a menos que você passá-lo explicitamente por referência, assim:

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);

Em sua segunda pergunta, $b não é uma referência a $a, mas uma cópia do $a.

Muito parecido com o primeiro exemplo, você pode fazer referência $a fazendo o seguinte:

$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);

Esta discussão é um pouco mais velhos, mas aqui algo que eu só vim através:

Tente este código:

$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

Note que não há amp para o $ params parâmetro e ainda altera o valor de US $ arr [ 'date']. Isto realmente não combinar com todas as outras explicações aqui e que eu pensava até agora.

Se eu clonar $ params [ 'date'] objeto, a 2ª emitido estadias data da mesma. Se eu apenas configurá-lo para uma string que não afeta a saída de qualquer um.

matrizes em PHP são passados ??para funções por valor, por padrão, a menos que você passá-los explicitamente por referência, como mostra o seguinte trecho:

$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

Aqui está a saída:

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

Para estender uma das respostas, também subarrays de matrizes multidimensionais são passados ??por valor, a menos que explicitamente passou por referência.

<?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

O resultado é:

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)
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top