복붙노트

PHP의 배열이 값 또는 참조로 전달됩니까?

PHP

PHP의 배열이 값 또는 참조로 전달됩니까?

배열이 메서드 또는 함수에 인수로 전달되면 참조로 전달됩니까?

이 일을하는 것은 어떨까요?

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

$ b는 $ a에 대한 참조입니까?

해결법

  1. ==============================

    1.질문의 두 번째 부분은 설명서의 배열 페이지를 참조하십시오.

    질문의 두 번째 부분은 설명서의 배열 페이지를 참조하십시오.

    그리고 주어진 예제 :

    <?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 섹션을 주저하지 말고 질문에 대한 답을해야합니다.

  2. ==============================

    2.귀하의 첫 번째 질문에 관해서는 배열은 당신이 호출하는 메서드 / 함수 내에서 수정되지 않는 한 참조로 전달됩니다. 메서드 / 함수 내에서 배열을 수정하려고하면 먼저 메서드의 복사본이 만들어지고 복사본 만 수정됩니다. 이것은 실제로 배열이 값으로 전달 된 것처럼 보이게합니다.

    귀하의 첫 번째 질문에 관해서는 배열은 당신이 호출하는 메서드 / 함수 내에서 수정되지 않는 한 참조로 전달됩니다. 메서드 / 함수 내에서 배열을 수정하려고하면 먼저 메서드의 복사본이 만들어지고 복사본 만 수정됩니다. 이것은 실제로 배열이 값으로 전달 된 것처럼 보이게합니다.

    예를 들어,이 첫 번째 경우에 매개 변수 정의에서 & 문자를 사용하여 $ 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
    }
    

    참고 - 이것을 "lazy copy"또는 "copy-on-write"라고합니다.

  3. ==============================

    3.a) 메서드 / 함수는 배열 인자 => 암시 적 (내부) 참조 만 읽는다. b) 메서드 / 함수가 배열 인수 => 값을 수정합니다. c) 메소드 / 함수 배열 인수는 명시 적으로 참조 (앰퍼샌드 포함) => 명시 적 (사용자 - 랜드) 참조로 표시됩니다.

    a) 메서드 / 함수는 배열 인자 => 암시 적 (내부) 참조 만 읽는다. b) 메서드 / 함수가 배열 인수 => 값을 수정합니다. c) 메소드 / 함수 배열 인수는 명시 적으로 참조 (앰퍼샌드 포함) => 명시 적 (사용자 - 랜드) 참조로 표시됩니다.

    아니면 이거: - 앰퍼샌드가 아닌 배열 매개 변수 : 참조로 전달됩니다. 기입 조작에 의해, 배열의 새로운 카피가 변경됩니다. 카피는 최초의 기입 해에 작성됩니다. - 앰퍼샌드 배열 매개 변수 : 참조로 전달됩니다. 기입 조작에 의해, 원의 배열이 변경됩니다.

    기억하십시오 - PHP는 앰퍼샌드가 아닌 배열 매개 변수에 쓸 순간에 값 복사를 수행합니다. 이것이 바로 복사 중 복사의 의미입니다. 나는이 행동의 C 소스를 보여주고 싶지만 그곳에는 무서운 것이있다. xdebug_debug_zval ()을 더 잘 사용하십시오.

    파스칼 마틴이 옳았다. Kosta Kontos는 훨씬 그렇습니다.

    그것은 달려있다.

    나는 내 자신을 위해 이것을 쓰고 있다고 생각한다. 나는 블로그 또는 뭔가를 가져야한다. ..

    사람들이 참조 (또는 포인터)에 관해 이야기 할 때마다, 그들은 대개 logomachy로 끝납니다 (이 스레드를보세요). PHP는 유서 깊은 언어이기 때문에, (비록 위의 답변을 요약해도) 혼란에 빠뜨릴 것이라고 생각했습니다. 왜냐하면 두 사람이 동시에 맞을지라도 머리를 하나의 답으로 분해하는 것이 낫습니다.

    먼저, 흑백 방식으로 대답하지 않으면 당신이 보잘것 없다는 것을 알아야합니다. 상황은 "예 / 아니오"보다 복잡합니다.

    보시다시피, 전체 by-value / by-reference는 메서드 / 함수 범위에서 정확히 배열과 관련된 작업과 매우 관련이 있습니다 : 읽기 또는 수정?

    설명서에 다음과 같이 쓰여 있습니다 (강조).

    내가 말할 수있는 한 크고 진지하고 정직한 신 프로그래머가 참조에 관해 말할 때 대개 그 참조의 가치를 바꾸는 것에 대해 이야기합니다. 그리고 그것은 매뉴얼에서 말한 것과 정확히 같습니다. 함수에서 값을 변경하려면 PHP가 "값별로 전달"을 수행하는 것으로 간주하십시오.

    그들이 언급하지 않은 또 다른 사례가 있습니다. 내가 무엇인가를 바꾸지 않으면 어떻게 읽습니까? 명시 적으로 참조를 표시하지 않는 메서드에 배열을 전달하고 함수 범위에서 해당 배열을 변경하지 않으면 어떻게됩니까? 일명 :

    <?php
    function printArray($array) {}
    $x = array(1);
    printArray($x);
    

    읽기, 내 동료 여행자.

    똑같은 크고 진지한 프로그래머들이 더 심각 해지면 참조와 관련하여 "메모리 최적화"에 대해 이야기합니다. PHP도 그렇습니다. PHP는 동적으로 느슨하게 형식화 된 언어이므로 쓰기시 복사 및 참조 계산을 사용하므로 그 이유가 있습니다.

    커다란 배열을 다양한 함수에 전달하는 것은 이상적이지 않으며, PHP는 그것들의 복사본을 만들어내는 것이 이상적이지 않을 것입니다 (결국 "pass-by-value"가하는 것입니다).

    <?php
    
    // filling an array with 10000 elements of int 1
    // let's say it grabs 3 mb from you 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);
    

    자, 실제로이 값이 패스라면, 그 배열의 복사본이 2 개 있기 때문에 3MB + RAM이 사라질 것입니다. 맞습니까?

    잘못된. 우리가 $ arr 변수를 변경하지 않는 한 그것은 메모리에 대한 참조입니다. 너는 단지 그것을 보지 못한다. 이것이 PHP가 내부와 명시 적 (앰퍼샌드 포함)을 구별하기 위해 & someVar에 대해 이야기 할 때 사용자 영역 참조를 언급하는 이유입니다.

    따라서 배열이 메서드 나 함수에 인수로 전달되면 참조로 전달됩니까?

    나는 세 가지 (예, 세 가지)의 경우를 생각해 냈습니다. a) 메서드 / 함수는 배열 인수 만 읽습니다. b) 메서드 / 함수가 배열 인수를 수정합니다. c) 메소드 / 함수 배열 인수는 명시 적으로 참조로 표시됩니다 (앰퍼샌드 포함)

    우선 배열이 실제로 먹는 메모리 양을 봅시다 (여기에서 실행하십시오) :

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

    그 많은 바이트. 큰.

    이제는 해당 배열을 인수로만 읽는 함수를 만들고 읽기 논리에 필요한 메모리 양을 봅시다.

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

    맞춰 볼래? 나는 80을 얻는다! 직접보십시오. 이것은 PHP 매뉴얼에서 생략 한 부분입니다. $ arr 매개 변수가 실제로 전달 된 값은 1331840 바이트와 비슷합니다. $ arr이 참조처럼 작동하는 것 같지 않습니까? 내부 참조가 참조이기 때문입니다.

    이제 param에서 읽는 대신에 param에 쓰자.

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

    다시 말하지만, 직접 보아라.하지만 나에게는 1331840에 가깝다.이 경우 배열은 실제로 $ arr에 복사 중이다.

    이제 명시 적 참조에 대한 쓰기 작업이 얼마나 많은 메모리를 사용하는지 살펴 보겠습니다 (여기에서 실행) - 함수 서명의 앰퍼샌드를 확인하십시오.

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

    제 내기는 당신이 200 점을 얻는 것입니다! 따라서 앰퍼샌드가 아닌 매개 변수에서 읽는 것만큼 메모리를 많이 사용합니다.

  4. ==============================

    4.기본적으로

    기본적으로

    참고 : 최적화로 모든 단일 값은 함수 내부에서 수정 될 때까지 참조로 전달됩니다. 수정 된 값이 참조에 의해 전달되면 값이 복사되고 사본이 수정됩니다.

  5. ==============================

    5.PHP에서 배열이 메서드 나 함수에 전달되면 명시 적으로 참조로 전달하지 않으면 값에 의해 전달됩니다. 예 :

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

    두 번째 질문에서 $ 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);
    
  6. ==============================

    6.이 스레드는 약간 나이가 들었지만, 여기에 나온 것은 뭔가 있습니다 :

    이 스레드는 약간 나이가 들었지만, 여기에 나온 것은 뭔가 있습니다 :

    이 코드를보십시오 :

    $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'] 객체를 복제하면 두 번째로 출력 된 날짜가 그대로 유지됩니다. 방금 문자열로 설정하면 출력에도 영향을주지 않습니다.

  7. ==============================

    7.PHP에서는 배열이 명시 적으로 참조로 전달되지 않는 한 기본적으로 값에 의해 함수에 전달됩니다. 다음 스 니펫이 보여줍니다.

    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)
    }
    
  8. from https://stackoverflow.com/questions/2030906/are-arrays-in-php-passed-by-value-or-by-reference by cc-by-sa and MIT license