문제

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

이 작업은 어떻습니까 :

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

~이다 $b 에 대한 참조 $a?

도움이 되었습니까?

해결책

질문의 두 번째 부분은 매뉴얼의 배열 페이지, 어느 상태 (인용) :

배열 할당에는 항상 가치 복사가 포함됩니다. 참조 연산자를 사용하여 배열을 참조로 복사하십시오.

주어진 예 :

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

이번에는 배열이 "참조로"전달되었습니다.


주저하지 마십시오 참고 문헌이 설명되었습니다 매뉴얼 섹션 : 몇 가지 질문에 답해야합니다 ;-)

다른 팁

첫 번째 질문과 관련하여 배열은 호출하는 메소드 / 기능 내에서 수정되지 않는 한 참조별로 전달됩니다. 메소드 / 함수 내에서 배열을 수정하려고하면 사본의 사본이 먼저 작성된 다음 사본 만 수정됩니다. 이것은 실제로 실제로 그렇지 않을 때 배열의 가치로 전달되는 것처럼 보입니다.

예를 들어,이 첫 번째 경우, 당신은 참조로 $ 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
}

참고-이것은 "게으른 사본"또는 "Copy-on-Write"로 알려져 있습니다.

tl; dr

a) 방법/기능 만 읽습니다 배열 인수 => 암시 적 (내부) 참조
b) 방법/기능 수정합니다 배열 인수 =>
c) 메소드/함수 배열 인수는 기준으로 명시 적으로 표시됩니다 (암페어와 함께) => 명시 적 (사용자 랜드) 참조

아니면 이거:
- 비 ampers 및 배열 매개 변수: 참조로 통과; 작문 작업은 첫 번째 쓰기에 생성 된 새로운 배열 사본을 변경합니다.
- 암페어 및 배열 매개 변수: 참조로 통과; 작문 작업은 원래 배열을 변경합니다.

기억 - PHP는 값 - 카피를 수행합니다 당신이 쓰는 순간 비 ampers 및 배열 매개 변수에. 그게 뭐야 copy-on-write 수단. 나는 당신 에게이 행동의 C 출처를 보여주고 싶습니다. 그러나 그것은 거기에서 무섭습니다. 더 나은 사용 xdebug_debug_zval ().

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

대답

때에 따라 다르지.

긴 버전

나는 이것을 스스로 작성한다고 생각합니다. 블로그 나 뭔가 ...

사람들이 참고 문헌 (또는 그 문제에 대한 포인터)에 대해 이야기 할 때마다, 그들은 보통 로고로 끝납니다 (이것을보십시오. !).
PHP는 유서 깊은 언어이기 때문에 혼란에 더해야한다고 생각했습니다 (위의 답변에 대한 요약에도 불구하고). 두 사람이 동시에 옳을 수 있지만, 머리를 하나의 대답으로 함께 깨뜨리는 것이 좋습니다.

먼저, 당신은 그것을 알아야합니다 당신이 흑백으로 대답하지 않으면 당신은 pedant가 아닙니다.. 상황은 "예/아니오"보다 더 복잡합니다.

보시다시피, 전체 값/부당 회의는 메소드/기능 범위에서 해당 배열로 정확히 무엇을하고 있습니까? 읽거나 수정합니까?

PHP는 무엇을 말합니까? (일명 "변화에 따라")

그만큼 수동 이것을 말합니다 (강조 광산) :

기본적으로 기능 인수는입니다 가치로 통과했습니다 (따라서 함수 내의 인수의 가치가 변경, 함수 외부에서 변경되지 않습니다). 함수를 허용합니다 수정하다 그것의 주장은해야합니다 참조로 통과합니다.

항상 참조로 전달되는 함수에 대한 인수를 얻으려면 기능 정의의 인수 이름으로 Ampersand (&)를 전제합니다.

내가 알 수있는 한, 크고 진지하고 정직한 프로그래머가 참고 문헌에 대해 이야기 할 때, 그들은 일반적으로 그 참조의 가치를 변경합니다. 그리고 그것이 바로 매뉴얼이 말하는 것입니다. hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value".

그래도 언급하지 않은 또 다른 사례가 있습니다. 아무것도 바꾸지 않으면 어떻게해야합니까?
배열을 기준을 명시 적으로 표시하지 않는 메소드로 전달하고 기능 범위에서 해당 배열을 변경하지 않으면 어떻게해야합니까? 예 :

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

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

echo readAndDoStuffWithAnArray($x);

내 동료 여행자를 읽으십시오.

PHP는 실제로 무엇을합니까? (일명 "메모리 와이즈")

동일한 크고 심각한 프로그래머는 더욱 심각해지면 참고 문헌과 관련하여 "메모리 최적화"에 대해 이야기합니다. PHP도 마찬가지입니다. 왜냐하면 PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting, 그게 .

거대한 배열을 다양한 기능으로 전달하는 것은 이상적이지 않을 것입니다. PHP는 그 사본을 만들기 위해 (결국 "통과 별"하는 일입니다) :

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

자, 이것이 실제로 통과하다면, 우리는 3MB+ 램이 사라 졌을 것입니다. 해당 배열의 사본이 맞습니까?

잘못된. 우리가 바꾸지 않는 한 $arr 변수, 그것은 참조입니다. 메모리 측정. 당신은 그것을 보지 못합니다. 그것이 PHP입니다 언급 사용자 랜드 참조 이야기 할 때 &$someVar, 내부와 명시 적 (암페어와 함께)을 구별하기 위해.

사리

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

나는 생각해 냈다 (예, 세 가지) 사례 :
a) 방법/기능 만 읽습니다 배열 인수
b) 방법/기능 수정합니다 배열 인수
c) 메소드/함수 배열 인수는 명시 적으로 참조로 표시됩니다 (암페어와 함께)


먼저, 배열이 실제로 먹는 메모리를 보자 여기):

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

그 많은 바이트. 엄청난.

a) 방법/기능 만 읽습니다 배열 인수

이제 기능을 만들어 봅시다 만 읽습니다 인수로서의 배열은 읽기 논리가 얼마나 많은 메모리를 취하는지 볼 것입니다.

<?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 Param은 실제로 가치가 전달되었으며 비슷한 것을 볼 수 있습니다. 1331840 바이트. 그것은 것 같습니다 $arr ~이다 참조 - 내부 참조.

b) 방법/기능 수정합니다 배열 인수

자, 가자 쓰다

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

c) 메소드/함수 배열 인수는 명시 적으로 참조로 표시됩니다 (암페어와 함께)

이제 메모리가 얼마나되는지 봅시다 명시 적 참조에 대한 쓰기 작업 테이크 (실행 여기) - 함수 서명의 앰퍼 and에 주목하십시오.

<?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 Max를 얻는다는 것입니다! 그래서 이것은 거의 많은 기억을 먹습니다 비 ampers 및 매개 변수에서 읽습니다.

기본적으로

  1. 프리미티브는 가치로 전달됩니다. Java가 아닌 String은 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" } } 
    

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

배열이 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);

이 스레드는 조금 오래되었지만 여기서 내가 방금 겪은 것입니다.

이 코드를 시도하십시오 :

$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 매개 변수에는 AMP가 없지만 여전히 $ ARR [ 'Date']의 값을 변경합니다. 이것은 여기서 다른 모든 설명과 지금까지 내가 생각한 것과 실제로 일치하지 않습니다.

$ params [ 'date'] 객체를 복제하면 두 번째 출력 날짜가 동일하게 유지됩니다. 방금 문자열로 설정하면 출력에도 영향을 미치지 않습니다.

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

답 중 하나를 확장하기 위해 다차원 배열의 서브 롤리 어레이는 참조로 설명 적으로 전달되지 않는 한 값으로 전달됩니다.

<?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)
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top