PHP 메모리의 객체 및 참조 소개
게시 됨: 2022-03-11PHP가 메모리에서 변수와 개체를 관리하는 방법을 더 잘 이해하기 위해 PHP 인증을 위해 공부하는 동안 이 기사의 초안을 처음 작성했습니다. 많은 연구 끝에 내 질문에 대한 답을 찾기가 쉽지 않다는 것을 깨달았고, 일단 질문을 마친 후 사람들이 한 곳에서 모든 정보를 찾을 수 있도록 정보를 문서화하기로 결정했습니다.
이 기사에서는 객체 및 변수 참조가 메모리에서 제어되는 방식에 대해 설명합니다. 이 문제는 토론과 다양한 의견을 생성할 수 있는 문제이기 때문입니다. 숙고해야 할 한 가지 질문은 "기본적으로 개체가 PHP에서 참조로 전달됩니까 아니면 복사로 전달됩니까?"입니다. PHP에 없는 참조에 대해 먼저 이야기하겠습니다. 두 번째로 그것들 이 무엇인지 논의하고 마지막으로 PHP에서 가비지 수집기가 어떻게 작동하는지 살펴보겠습니다.
$a = new Foo();
? 오늘날 메모리는 과거만큼 비싸지 않고 리소스가 제한적입니다. 그러나 훌륭한 PHP 개발자는 응용 프로그램을 실행하는 동안 변수와 개체가 내부적으로 관리되는 방식을 알고 이해하는 것이 여전히 중요합니다.
PHP의 객체와 참조
많은 사람들이 PHP 책과 온라인에서 PHP의 객체는 기본적으로 참조로 전달된다고 말합니다. 다른 사람들은 PHP의 객체가 복사에 의해 할당된다고 말합니다. 어떤 문장이 옳은지 알아내려면 먼저 PHP에서 참조가 무엇인지(그리고 그렇지 않은) 분석해야 합니다.
PHP에서 참조 가 아닌 것은 무엇입니까?
PHP에서 참조가 무엇인지 아는 것보다 더 중요한 것은 참조가 무엇 인지 아는 것입니다. PHP에서 참조는 C 스타일 포인터가 아닙니다. C 포인터로 할 수 있는 것처럼 참조로 산술 연산을 수행할 수 없습니다. 왜요? C와 달리 PHP 참조는 메모리 위치를 나타내는 숫자가 아니기 때문에 실제로 메모리 주소가 아니기 때문입니다. 그렇다면 레퍼런스 란 무엇일까요?
PHP에서 참조란 무엇 입니까 ?
PHP에서 참조는 두 개의 다른 변수가 단일 값을 읽고 쓸 수 있도록 하는 "별칭"입니다. 다시 말해, 이름이 다른 변수에서 동일한 값에 액세스하여 동일한 변수인 것처럼 동작하도록 하는 메커니즘입니다. PHP에서 변수 이름과 변수의 내용은 "기호 테이블"이라고 하는 것과 연결된 완전히 다른 두 가지입니다. 따라서 참조를 만들 때 기호 테이블에 해당 변수에 대한 별칭을 추가하기만 하면 됩니다. 다음 코드가 있다고 가정합니다.
$a = new Foo();
위의 명령문이 실행되면 변수 $a
가 메모리에 생성되고 Foo
유형의 객체가 메모리에 생성되며 $a
변수가 "참조"(또는 , 또는 가리키거나 부르고 싶은 모든 것) Foo
객체이지만 그 객체 자체에 대한 포인터 는 아닙니다. 개념적으로 다음과 같은 그림이 있습니다.
팝 퀴즈: 이것을 실행하면 어떻게 될까요?
$b = $a;
$b
가 $a
a의 참조가 되는 것은 아닙니다. $b
가 $a
a 의 복사본이라고 말할 수도 없습니다. 실제로 일어난 일은 메모리에 새 변수 $b
를 만든 다음 $b
변수가 $a
a와 동일한 Foo
객체를 참조한다는 것을 나타내는 기호 테이블에 새 항목을 추가한 것입니다. 따라서 시각적으로 이 그림에 표시된 것과 유사한 것이 있습니다.
이제 다음을 실행하면:
$c = &$a;
우리는 메모리에 세 번째 변수 $c
를 만들지만 $c
c에 대한 기호 테이블의 새 항목은 만들지 않습니다 . 대신, 기호 테이블에서 $c
는 $a
a 에 대한 별칭이므로 동일하게 동작하지만 $c
는 포인터에 대한 포인터 라는 것을 생성하는 C와 달리 $a
에 대한 포인터가 아닙니다. 시각화하기 위해 이 그림에 표시된 것과 유사한 것이 있습니다.
이 세 변수 중 하나의 값을 수정하려는 경우(즉, 새 값 쓰기), PHP는 변수 $b
의 내용과 $a
/ 쌍을 분리하기 위해 메모리에 새 z_val
구조를 생성해야 합니다. $c
를 사용하여 다른 값에 영향을 주지 않고 각각 독립적으로 수정할 수 있습니다. 따라서 이전 스크립트에 다음 줄을 추가하면:

$b = new Bar();
메모리에는 다음 그림과 같은 상황이 있습니다.
이제 더 완전한 예를 살펴보겠습니다.
<?php class myClass { public $var; function __construct() { $this->var = 1; } function inc() { return ++$this->var; } } $a = new myClass(); // $a "references" a Foo object $b = $a; //b also references the same Foo object as a //($a) == ($b) == <id> of Foo object, but a and b are different entries in symbols table echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); $c = &$a; //$c is an alias of $a //($a, $c) == <id> of Foo object, c is an alias of a in the symbols table echo "$c = ";var_dump($c); $a = NULL; //The entry in the symbols table which links "$a" with Foo object is removed //Since that entry was removed, $c is not related to Foo anymore //Anyway, Foo still exists in memory and it is still linked by $b echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); echo "$c = ";var_dump($c); echo "$b->var: ".$b->inc(); echo "$b->var: ".$b->inc(); $b = NULL; //The entry in the symbols table which links "$b" with the Foo object is removed //There are no more entries in the symbols table linked to Foo, //So, Foo is not referenced anymore and can be deleted by the garbage collector echo "$b = ";var_dump($b);
위의 스크립트 구현으로 생성된 출력은 다음과 같습니다.
$a = object(myClass)#1 (1) { ["var"]=> int(1) } $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = object(myClass)#1 (1) { ["var"]=> int(1) } $a = NULL $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = NULL $b->var: 2 $b->var: 3 $b = NULL
PHP 가비지 컬렉션
마지막으로 PHP 가비지 컬렉션이 버전 5.3에 도입된 이후 어떻게 작동하는지 봅시다. PHP 메모리의 객체 또는 변수는 기호 테이블에 해당 객체에 대한 참조가 없을 때 PHP 가비지 수집기에 의해 제거됩니다. 즉, PHP는 객체가 생성될 때부터 객체의 참조 카운터를 유지하므로 스크립트 PHP를 실행하는 동안 카운터가 "가리키는" 변수를 기반으로 해당 참조 카운터를 증가 및 감소시킵니다. 참조 횟수가 0에 도달하면(즉, 해당 개체를 참조하는 것이 없으므로 사용되지 않음) PHP는 해당 개체를 제거 가능한 것으로 표시하여 PHP 가비지 수집기의 다음 패스에서 메모리에서 제거됩니다. , 재사용을 위해 해당 공간을 확보합니다. PHP 가비지 수집이 작동하는 방식에 대해 더 자세히 알고 싶다면 이 문서를 읽어보세요.
마무리 생각
PHP가 메모리에서 개체와 변수를 처리하는 방법과 PHP 가비지 수집기에 의해 제거되어야 하는 개체를 "선택"하는 방법을 조금 설명했으면 합니다.
PHP가 내부적으로 메모리의 변수와 개체를 관리하는 방법을 이해했으므로 이제 랩톱을 들고 배운 내용을 증명하기 위해 몇 가지 코드를 실험해 보십시오. 변수와 참조를 가지고 놀아보십시오. 또한 변수 값을 변경하면 변수를 참조하는 다른 변수의 값에 어떤 영향을 미칠 수 있는지 실험해 보십시오. 여기 당신을 위한 질문이 있습니다: 아래 코드가 실행된 후 $ $a
와 $b
의 값은 무엇입니까?
$a = '1'; $b = &$a; $b = "2$b";
PHP 성능 기능에 대해 더 알고 싶다면 동료 Toptaler Vilson Duka의 이 게시물을 확인하십시오.