web-dev-qa-db-ja.com

PHPの配列は、値または参照によって渡されますか?

配列が引数としてメソッドまたは関数に渡されるとき、参照渡しですか?

これについてはどうですか:

$a = array(1,2,3);
$b = $a;

$b$aへの参照ですか?

241
Frank

質問の2番目の部分については、(quoting)を示す マニュアルの配列ページ を参照してください。

配列の割り当てには、常に値のコピーが含まれます。参照演算子を使用して、参照によって配列をコピーします。

そして、与えられた例:

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2, 3)

$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>


最初の部分では、確実な最善の方法は試してみることです;-)

次のコード例を検討してください。

function my_func($a) {
    $a[] = 30;
}

$arr = array(10, 20);
my_func($arr);
var_dump($arr);

次の出力が得られます。

array
  0 => int 10
  1 => int 20

これは、関数がパラメーターとして渡された「外部」配列を変更していないことを示します。参照ではなくコピーとして渡されます。

参照渡しする場合は、次のように関数を変更する必要があります。

function my_func(& $a) {
    $a[] = 30;
}

そして、出力は次のようになります。

array
  0 => int 10
  1 => int 20
  2 => int 30

今回は、配列が「参照渡し」で渡されたためです。


マニュアルの References Explained セクションを読むことをheしないでください。あなたの質問のいくつかに答えるべきです;-)

259
Pascal MARTIN

最初の質問に関して、配列は、呼び出しているメソッド/関数内で変更されない限り、参照によって渡されます。メソッド/関数内で配列を変更しようとすると、最初にそのコピーが作成され、次にコピーのみが変更されます。これにより、実際には配列ではなく値によって配列が渡されるように見えます。

たとえば、この最初のケースでは、参照によって$ my_arrayを受け入れるように関数を定義していなくても(パラメーター定義で&文字を使用して)、参照によって渡されます(つまり、メモリを浪費しません)不要なコピー)。

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
}

ただし、配列を変更すると、最初に配列のコピーが作成されます(より多くのメモリを使用しますが、元の配列は影響を受けません)。

function handle_array($my_array) {

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

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

参考までに、これは「遅延コピー」または「コピーオンライト」として知られています。

106
Kosta Kontos

デフォルトで

  1. プリミティブは値で渡されます。 Javaとは異なり、文字列はPHPではプリミティブです
  2. プリミティブの配列は値で渡されます
  3. オブジェクトは参照で渡されます
  4. オブジェクトの配列は値(配列)で渡されますが、各オブジェクトは参照で渡されます。

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

注:最適化として、関数内で変更されるまで、すべての単一の値が参照として渡されます。変更され、値が参照によって渡された場合、コピーされ、コピーが変更されます。

11
magallanes

PHPのメソッドまたは関数に配列が渡される場合、明示的に参照渡しする場合を除き、値で渡されます。

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

2番目の質問では、$b$aへの参照ではなく、$aのコピーです。

最初の例と同様に、次を実行することで$aを参照できます。

$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);
4
Corey Ballou

このスレッドは少し古いですが、ここで私が出会ったもの:

このコードを試してください:

$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

$ paramsパラメータ用のアンプはありませんが、それでも$ arr ['date']の値を変更することに注意してください。これは、ここにある他のすべての説明や、今まで考えていたものとは実際には一致しません。

$ params ['date']オブジェクトを複製した場合、2番目に出力される日付は変わりません。文字列に設定しただけでも、出力には影響しません。

1
robbash

答えの1つを拡張するために、参照によって明示的に渡されない限り、多次元配列のサブ配列も値によって渡されます。

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

結果は次のとおりです。

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)
}
0
K.Karamazen

PHPでは、次のスニペットが示すように、参照によって明示的に渡す場合を除き、配列はデフォルトで値によって関数に渡されます。

$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

出力は次のとおりです。

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