1) 배열이 메소드 또는 함수에 인수로 전달되면 참조 또는 값으로 전달됩니까?
2) 배열을 변수에 할당 할 때 새 변수가 원래 배열에 대한 참조입니까, 아니면 새 사본입니까?
이 작업은 어떻습니까 :
$a = array(1,2,3);
$b = $a;
에 $b
대한 참조 $a
입니까?
1) 배열이 메소드 또는 함수에 인수로 전달되면 참조 또는 값으로 전달됩니까?
2) 배열을 변수에 할당 할 때 새 변수가 원래 배열에 대한 참조입니까, 아니면 새 사본입니까?
이 작업은 어떻습니까 :
$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
마찬가지로 이번에는 배열이 "참조로"전달되었습니다.
망설이지 말고 매뉴얼의 Explained 섹션 을 읽으십시오 : 그것은 당신의 질문에 대답해야합니다 ;-)
&
, 그래, 그것은해야합니다 - 볼 php.net/manual/en/...
첫 번째 질문과 관련하여 배열은 호출하는 메소드 / 함수 내에서 수정되지 않는 한 참조로 전달됩니다. 메소드 / 함수 내에서 배열을 수정하려고 시도하면 먼저 사본을 만든 다음 사본 만 수정합니다. 따라서 실제로는 그렇지 않은 경우 배열이 값으로 전달되는 것처럼 보입니다.
예를 들어,이 첫 번째 경우, 매개 변수 정의에서 & 문자를 사용하여 참조로 $ 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
}
참고로 "게으른 사본"또는 "기록 중 복사"라고합니다.
a) 메소드 / 함수 는 배열 인수 => 내재적 (내부) 참조 만 읽습니다 .
b) 메소드 / 함수 는 배열 인수 => 값을 수정 합니다.
c) 메소드 / 함수 배열 인수는 명시 적으로 참조로 표시됩니다 (앰퍼샌드) => 명시 적 (사용자 영역) 참조
또는 :
- 비 앰퍼샌드 배열 매개 변수 : 참조로 전달; 기록 동작은 어레이의 새로운 사본을 변경하며,이 사본은 첫번째 기록에서 생성된다;
- 앰퍼샌드 배열 매개 변수 : 참조로 전달됩니다. 쓰기 작업은 원래 배열을 변경합니다.
기억하십시오-PHP는 앰퍼샌드가 아닌 배열 매개 변수에 쓰는 순간 값 복사를 수행 합니다 . 그것이 copy-on-write
의미 하는 바입니다. 이 행동의 C 소스를 보여 드리고 싶지만 무섭습니다. xdebug_debug_zval () 사용하는 것이 좋습니다 .
Pascal MARTIN이 옳았습니다. 코스타 콘 토스는 훨씬 더했다.
때에 따라 다르지.
나는 이것을 직접 작성하고 있다고 생각합니다. 블로그 나 뭔가가 있어야합니다 ...
사람들이 참조 (또는 그 문제에 대한 포인터)에 대해 이야기 할 때마다 대개 로고로 마무리됩니다 (이 스레드를 보십시오!).
PHP는 훌륭한 언어이기 때문에 혼란에 가담해야한다고 생각했습니다 (이 답변에 대한 요약이지만). 두 사람이 동시에 옳을 수 있지만, 머리를 하나로 묶어 하나의 답변으로 만드는 것이 좋습니다.
우선, 당신이 흑백으로 대답하지 않으면 당신은 pedant가 아니라는 것을 알아야합니다 . "예 / 아니오"보다 상황이 더 복잡합니다.
보시다시피 전체 값 / 참조 기준은 메소드 / 함수 범위에서 해당 배열로 수행하는 작업과 관련이 있습니다. 읽거나 수정합니까?
매뉴얼 이 (강조 광산)를 말한다 :
기본적으로 함수 인수는 값 으로 전달 되므로 함수 내의 인수 값이 변경 되면 함수 외부에서 변경되지 않습니다. 함수가 인수 를 수정할 수있게하려면 참조 로 전달 해야합니다 .
함수에 대한 인수가 항상 참조로 전달되도록하려면 함수 정의에서 앰퍼샌드 (&)를 인수 이름 앞에 추가하십시오.
내가 알 수있는 한, 크고 진지하고 정직한 하나님 프로그래머가 참조에 대해 이야기 할 때, 그들은 일반적으로 그 참조의 가치를 변경하는 것에 대해 이야기 합니다. 그리고 그것은 매뉴얼이 말하는 것입니다 : 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 is a dynamic, loosely typed language, that uses copy-on-write and reference counting
, 그건 왜 .
HUGE 배열을 다양한 함수에 전달하고 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 이상의 RAM이 사라졌습니다 .
잘못된. $arr
변수를 변경하지 않는 한 메모리 기준 입니다. 당신은 그것을 보지 못합니다. 그렇기 때문에 PHP 는 내부 및 명시 적 (앰퍼샌드 포함)을 구별하기 위해 에 대해 이야기 할 때 사용자-랜드 참조를 언급&$someVar
합니다.
그래서, when an array is passed as an argument to a method or function is it passed by reference?
나는 세 가지 (예, 세 가지) 경우를 생각해 냈습니다 :
a) 메소드 / 함수 는 배열 인수 만 읽습니다 .
b) 메소드 / 함수 는 배열 인수를 수정 합니다
. 앰퍼샌드)
먼저, 해당 배열이 실제로 먹는 메모리 양을 확인하십시오 ( 여기에서 실행 ).
<?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
참조처럼 행동하는 것 같습니다 . 내부 참조 인 참조 이기 때문 입니다 .
이제 그 매개 변수를 읽지 말고 그 매개 변수에 쓰 도록하겠습니다 :
<?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 최대를 얻는 것입니다! 따라서 이것은 앰퍼샌드가 아닌 매개 변수에서 읽는 것만큼이나 많은 메모리를 소비 합니다.
기본적으로
객체 배열은 값 (배열)으로 전달되지만 각 객체는 참조로 전달됩니다.
<?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( 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)
}
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)
}