PHP 변수는 값이나 참조로 전달됩니까?


답변:


311

PHP Documentation 에 따르면 가치가 있습니다.

기본적으로 함수 인수는 값으로 전달됩니다 (따라서 함수 내의 인수 값이 변경되면 함수 외부에서는 변경되지 않습니다). 함수가 인수를 수정할 수있게하려면 참조로 전달해야합니다.

함수에 대한 인수가 항상 참조로 전달되도록 하려면 함수 정의에서 인수 이름 앞에 앰퍼샌드 ( & )를 추가하십시오.

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}

$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>

4
나는 또한이 의심 (초보자)을 가졌다. 그래서 명확히하기 위해, 이것은 $str = add_some_extra($str);참조를 사용하지 않는 것과 같다 . 그렇다면 그 진정한 부가 가치는 무엇입니까?
Obmerk Kronen

7
당신이 된 경우 @Obmerk 하지 참조 의미하는 앰퍼샌드를 사용하여, 그것은 동등하지 않을 것입니다. 함수에 return 문이없는 방법 $str에주의하십시오.
알 수없는 개발자

@ObmerkKronen이 방법으로 수행하면 값을 반환하고 코드를 통해 값을 잡아야합니다. 그렇지 않으면 초기 변수는 동일하게 유지됩니다.
Nabeel Khan

참조로 전달에 성능상의 이점이 있는지 궁금합니다. 큰 배열을 전달하고 기본적으로 값으로 전달됩니다. 따라서 참조로 전화를 사용하면 성능면에서 이점이 있습니까 ??? (전체 프로세스 동안 배열 값을 변경하지 않고 유지)
Choxx

4
실제 이점은 여러 값을 조작 / 반환 할 수 있다는 것입니다. 참조로 변수를 전달할 수 있으며 여전히 함수가 무언가를 반환하도록 할 수 있습니다.
마틴 슈나이더

65

PHP에서, 기본적으로 객체는 참조 객체로 새로운 객체에 전달됩니다.

이 예를 참조하십시오 ........

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
   $obj->abc = 30;
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30

이제 이것을보십시오 ..............

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.

이제 이것을 참조하십시오 ..............

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue(&$obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.

나는 당신이 이것을 이해할 수 있기를 바랍니다.


1
이것은 PHP 객체가 어떻게 작동하는지 잘 보여줍니다.
프레데릭 Krautwald

2
첫 번째 예에서 obj의 참조 값이 함수에 전달되고 새 참조를 사용하여 obj의 변경 사항이 동일한 obj를 가리키는 다른 모든 참조에 반영됩니다. 두 번째 예, 다시 obj 참조의 값이 함수에 전달되고 함수가 새 obj를 가리 키도록 참조 값을 변경하면 이전 obj는 동일하게 유지됩니다. 세 번째 예에서 obj 참조 값의 참조가 함수에 전달되므로 함수의 변경 사항이 동일한 obj에서 작동합니다.
s-hunter

완벽한 예와 정확히 내가 생각한 일. 나는 (Javascript / node.js 배경에서) PHP를 처음 접했고 때때로 무슨 일이 일어나고 있는지 어려워하지만, 이것은 매우 분명합니다!
TKoL

이 예제는 불필요하게 복잡합니다. $y필요하지 않습니다- function changeValue안에 있어야 할 것이 class Y없기 때문에 관련이없는 두 가지 개념이 얽 힙니다. function changeValue바로 위의 외부 범위 로 이동 합니다 $x = new X();. 에 대한 모든 참조를 제거하십시오 $y. 이제 처음 두 예제는 $ x 만 남겨두고 세 번째 예제는 내용을로 변경합니다 new Y(). 당신이 덤프 있는지 확인하기 쉬울 것 어느 type$x- 모두 사실 X과는 Y포함하는 일이 $abc필드를 또한 입증 것과 무관
ToolmakerSteve

60

객체가 함수에 전달되는 방식과 참조가 전달하는 방식에 의해 많은 사람들이 혼란스러워하는 것 같습니다. 객체 변수는 여전히 값으로 전달되며, PHP5에서 전달되는 값은 참조 핸들입니다. 증거로 :

<?php
class Holder {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return $this->value;
    }
}

function swap($x, $y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

출력 :

a, b

하기 참조에 의해 전달 수단 우리는 호출자으로 볼 수 있습니다 변수를 수정할 수 있습니다. 위의 코드가 분명히하지 않습니다. 교체 기능을 다음과 같이 변경해야합니다.

<?php
function swap(&$x, &$y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

출력 :

b, a

참조로 전달하기 위해.


18
이 증거는 오해라고 생각합니다. 참조를 바꾸려고 한 것 같습니다. 객체 할당 방법에 문제가 있습니다. 불변 인 참조를 다시 할당하고 있습니다. 내부에서 변경할 수있는 값입니다. 스왑 재정의가 이제 ** x를 통과하여 * x를 변경할 수 있습니다. 문제는 $ x = $ y가 $ x가 원래 가리키는 것을 바꿀 것이라고 생각하고 있습니다.
grantwparks 2016 년

9
이것은 증거가 아닙니다 . 첫 번째 예제의 결과는 전체 객체의 현재 값이 swap함수 에 전달 된 경우와 정확히 일치 합니다. 즉, 객체가 "값에 의해 전달 된"경우. 반면에 객체 핸들이 함수에 전달되면 실제로 예상되는 것과 정확히 일치합니다. 귀하의 코드는이 두 경우를 구별하지 않습니다.
EML

31

http://www.php.net/manual/en/migration5.oop.php

PHP 5에는 새로운 객체 모델이 있습니다. PHP의 객체 처리가 완전히 다시 작성되어 성능과 기능이 향상되었습니다. 이전 버전의 PHP에서는 객체가 기본 유형 (예 : 정수 및 문자열)과 같이 처리되었습니다. 이 방법의 단점은 전체 객체가 의미 적으로 변수가 할당 될 때 복사되거나 매개 변수로 메서드에 전달되었다는 것입니다. 새로운 접근 방식에서 객체는 값이 아닌 핸들로 참조됩니다 (핸들을 객체의 식별자로 생각할 수 있음).


25

PHP 변수는 값으로 할당되고, 값으로 함수에 전달되며, 객체를 포함 / 대표하는 경우 참조로 전달됩니다. &를 사용하여 변수를 참조로 전달할 수 있습니다.

값 / 참조 예에 의해 지정 :

$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";

print ("var1: $var1, var2: $var2, var3: $var3);

출력 할 것이다

var1 : 테스트, var2 : 최종 테스트, var3 : 최종 테스트

가치 / 참조 시험에 통과 :

$var1 = "foo";
$var2 = "bar";

changeThem($var1, $var2);

print "var1: $var1, var2: $var2";

function changeThem($var1, &$var2){
    $var1 = "FOO";
    $var2 = "BAR";
}

출력 :

var1 : foo, var2 바

참조 예를 통해 전달 된 객체 변수 :

class Foo{
    public $var1;

    function __construct(){
        $this->var1 = "foo";
    }

    public function printFoo(){
        print $this->var1;
    }
}


$foo = new Foo();

changeFoo($foo);

$foo->printFoo();

function changeFoo($foo){
    $foo->var1 = "FOO";
}

출력 :

(마지막 예제는 아마도 더 좋을 것입니다 ...)


2
"객체"는 PHP5의 값이 아니며 "전달"될 수 없습니다. 의 값은 객체에$foo 대한 포인터 입니다. $foo되는 값에 의해 전달 함수에 changeFoo()로, changeFoo()과의 매개 변수를 선언하지 않았다 &.
newacct

9

참조로 변수를 함수에 전달할 수 있습니다. 이 함수는 원래 변수를 수정할 수 있습니다.

함수 정의에서 참조로 구절을 정의 할 수 있습니다.

<?php
function changeValue(&$var)
{
    $var++;
}

$result=5;
changeValue($result);

echo $result; // $result is 6 here
?>

6

어느 쪽이든 할 수 있습니다.

앞에 '&'기호를 넣으면 전달하는 변수가 하나의 원점과 같습니다. 즉, 사본을 만들지 않고 참조로 전달할 수 있습니다.

그래서

    $fred = 5;
    $larry = & $fred;
    $larry = 8;
    echo $fred;//this will output 8, as larry and fred are now the same reference.

2
이 기능은 더 이상 사용되지 않으며 경고를 생성합니다.
fijiaaron

5

기본 유형을 포함하는 변수는 PHP5에서 값으로 전달됩니다. 객체를 포함하는 변수는 참조로 전달됩니다. 2006 년 Linux Journal의 흥미로운 기사가 ​​있는데이 기사와 4와 5의 다른 OO 차이점을 언급했습니다.

http://www.linuxjournal.com/article/9170


함수의 매개 변수에 no가 없으면 모든 변수는 PHP의 값으로 전달됩니다 &.
newacct

1

객체는 PHP 5에서 참조로, PHP 4에서 값으로 전달됩니다. 변수는 기본적으로 값으로 전달됩니다!

여기를 읽으십시오 : http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html


"객체"는 PHP5의 값이 아니며 "전달"될 수 없습니다. 전달 된 함수의 매개 변수에없는 경우 모든 변수가 값으로 전달됩니다 &.
newacct

@newacct이별로 라고요? 객체는 다소 참조로 전달됩니다 . 나는 정의 &에서 매개 변수 앞에 정의되지 않은 경우에도 함수에 의해 PHP 객체가 수정 될 수 있다고 생각 했습니다. 값으로 전달 된 경우 범위에 포함 된 객체를 매개 변수로 영향을받지 않습니다.
Félix Gagnon-Grenier

3
@ FélixGagnon-Grenier : "개체"는 값이 아니며 "전달"될 수 없습니다. PHP5에서는 값이 "object"인 "variable"을 가질 수 없으며, 객체 참조 (즉, 객체에 대한 포인터) 인 값만 가질 수 있습니다. 물론 값으로 객체에 대한 포인터를 전달하거나 할당하고 그러한 수정을 수행하는 메소드를 호출하여 가리키는 객체를 수정할 수 있습니다. 그것은 참조로 전달하는 것과 아무 관련이 없습니다. 값의 유형과 매개 변수가 값별 / 참조 별인지는 독립적이며 직교적인 것입니다.
newacct December

1
class Holder
{
    private $value;

    public function __construct( $value )
    {
        $this->value = $value;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function setValue( $value )
    {
        return $this->value = $value;
    }
}

class Swap
{       
    public function SwapObjects( Holder $x, Holder $y )
    {
        $tmp = $x;

        $x = $y;

        $y = $tmp;
    }

    public function SwapValues( Holder $x, Holder $y )
    {
        $tmp = $x->getValue();

        $x->setValue($y->getValue());

        $y->setValue($tmp);
    }
}


$a1 = new Holder('a');

$b1 = new Holder('b');



$a2 = new Holder('a');

$b2 = new Holder('b');


Swap::SwapValues($a1, $b1);

Swap::SwapObjects($a2, $b2);



echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";

echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";

참조로 전달되지 않은 경우 속성을 여전히 수정할 수 있으므로주의하십시오.

산출:

스왑 객체 : b, a 스왑 값 : a, b


1

앞으로이 문제를 겪는 사람이라면 익명의 사용자가 게시 한 PHP 문서 에서이 보석을 공유하고 싶습니다 .

여기에 약간의 혼란이있는 것 같습니다. 포인터와 참조의 구별은 특별히 도움이되지 않습니다. 이미 게시 된 일부 "포괄적 인"예제의 동작은보다 단순한 통일 용어로 설명 할 수 있습니다. 예를 들어, Hayley의 코드는 예상 한대로 정확하게 수행하고 있습니다. (> = 5.3 사용)

첫 번째 원칙 : 포인터는 객체에 액세스하기위한 메모리 주소를 저장합니다. 객체가 할당 될 때마다 포인터가 생성됩니다. (나는 아직 Zend 엔진에 TOO를 깊이 파고 들지 않았지만 볼 수있는 한이 적용됩니다)

두 번째 원칙과 가장 혼란스러운 원인 : 변수에 함수를 전달하는 것은 기본적으로 값 전달로 수행됩니다. 즉, 사본을 사용하는 것입니다. "하지만 객체는 참조로 전달됩니다!" 여기와 자바 세계에서 공통된 오해. 나는 무엇의 사본을 말하지 않았다. 기본 전달은 값으로 수행됩니다. 항상. 그러나 복사되고 전달되는 것은 포인터입니다. "->"를 사용할 때는 물론 호출자 함수의 원래 변수와 동일한 내부에 액세스하게됩니다. "="를 사용하면 사본 만 재생됩니다.

세 번째 원칙 : "&"는 다른 변수 이름 / 포인터를 분리 할 때까지 다른 변수와 동일한 메모리 주소로 자동으로 영구적으로 설정합니다. 여기서 "별칭"이라는 용어를 사용하는 것이 맞습니다. "unset ()"으로 강제 분리 될 때까지 엉덩이에 두 개의 포인터를 연결하는 것으로 생각하십시오. 이 기능은 동일한 범위와 인수가 함수에 전달 될 때 모두 존재합니다. C와 C ++에서 더 명확한 "값으로 전달"과 "참조로 전달"사이의 특정 차이점으로 인해 전달 된 인수를 "참조"라고합니다.

기억하십시오 : 객체 자체가 아닌 객체에 대한 포인터가 함수에 전달됩니다. 이 포인터는 실제로 원본을 전달하기 위해 매개 변수 목록에서 "&"를 사용하지 않는 한 원본의 사본입니다. 개체의 내부를 파헤쳐야만 원본이 변경됩니다.

그리고 그들이 제공하는 예는 다음과 같습니다.

<?php

//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.

$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.

//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"

function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}

function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}

?>

JavaScript에 대한이 주제에 대해 광범위하고 자세한 블로그 게시물을 작성 했지만 PHP, C ++ 및 사람들이 가치에 따라 전달하는 것과 참조로 전달하는 것에 대해 혼란스러워하는 다른 언어에도 똑같이 적용된다고 생각합니다.

분명히 C ++과 같은 PHP는 참조로 전달하는 언어입니다. 기본적으로 객체는 값으로 전달됩니다. 객체를 저장하는 변수로 작업 할 때는 해당 변수를 포인터로 보는 데 도움이됩니다 (조립품 수준에서 기본적으로 변수이기 때문에). 값을 기준으로 포인터를 전달하면 포인터를 "추적"하고 가리키는 객체의 속성을 수정할 수 있습니다. 할 수없는 것은 다른 대상을 가리 키도록하는 것입니다. 참조에 의해 전달 된 것으로 명시 적으로 매개 변수를 선언 한 경우에만이를 수행 할 수 있습니다.


0

실제로 두 방법 모두 유효하지만 요구 사항에 따라 다릅니다. 참조로 전달 된 값은 종종 스크립트 속도를 느리게합니다. 따라서 실행 시간을 고려하여 값으로 변수를 전달하는 것이 좋습니다. 또한 값으로 변수를 전달할 때 코드 흐름이 더 일관됩니다.


0

원래 변수를 간단히 변경하고 새 값이 할당 된 동일한 변수 이름으로 다시 되돌리려는 경우 함수에이 기능을 사용하십시오.

function add(&$var){ // The &amp; is before the argument $var
   $var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced

-7

버전에 따라 4는 값 기준이고 5는 참조 기준입니다.


11
나는 이것이 사실이라고 생각하지 않습니다.
Nick Heiner

@ Karl Seguin, 부분적으로 사실입니다. PHP5 객체는 기본적으로 값으로 전달되었지만 5부터는 핸들러를 통해 전달되었습니다. 실제로는 php.net/manual/en/language 를 통해 객체 속성을 수정할 수 있기 때문에 실제로는 예외로 처리 할 수 ​​있습니다 . oop5.references.php .
Adam Faryna
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.