2011-12-15 2 views
14

우리는 클래스 CFoo이 있다고 가정 해 봅시다. 다음 예제에서 CFoo::__destruct()은 언제 호출됩니까? 스크립트가 더 이상 액세스 할 수 없을 것입니다 MyPHPFunc$foo 때문에의 범위를 종료 할 때이 예에서 PHP에서 클래스 객체가 파괴되는시기를 결정하는 것은 무엇입니까?

function MyPHPFunc() 
{ 
    $foo = new CFoo(); 

    . . . 

    // When/where/how does $foo get destroyed/deleted? 
} 

은 소멸자가 호출 될 것이다?

+0

스크립트가 종료 될 때 (종료 시퀀스 중). –

+5

소스로 먼저 이동하십시오 : PHP 매뉴얼 .. 인용구 : "소멸자 메소드는 특정 오브젝트에 대한 다른 참조가 없거나 종료 순서에 관계없이 호출됩니다."그래서 더 이상 사용하지 않으면 또는 스크립트가 끝나거나 죽습니다. http://www.php.net/manual/en/language.oop5.decon.php – mishu

답변

33

PHP에서 모든 값은 zval에 저장됩니다. 그 사람의 zval에는 실제 데이터, 유형 정보가 포함되어 있으며 질문에 중요합니다 (참조 카운트). refcountzval이 해제됩니다 0에 도달 객체 소멸자가 호출되는 즉시

$a = new B; // $a   points to zval(new B) with refcount=1 
$b = $a; // $a, $b  point to zval(new B) with refcount=2 (+1) 
$c = $b; // $a, $b, $c point to zval(new B) with refcount=3 (+1) 
unset($a); //  $b, $c point to zval(new B) with refcount=2 (-1) 

: 다음 코드에서보세요.함수 (또는 방법)의 범위를 이탈

$a = new B; // refcount=1 
$b = $a; // refcount=2 
unset($a); // refcount=1 => no destruct as refcount > 0, even though unset() was called! 
  • :

    $a = new B; // refcount=1 
    unset($a); // refcount=0 => __destruct! 
    

    :하지만 변수를 보내고

    • unset : 여기

      는 일부 refcount0 도달 예

      function a() { 
          $a = new B; // refcount=1 
      }    // refcount=0 => __destruct! (as $a does not exist anymore) 
      
    • 스크립트 실행 끝

      $a = new B; // refcount=1 
      die();  // refcount=0 => __destruct! (on script execution end all vars are freed) 
      // doesn't need to be die(), can be just normal execution end 
      

    이 분명 refcount의 감소로 이어지는 모든 조건,하지만 당신은 가장 일반적으로 충족하는 사람이 아니다.

    또한 PHP 5.3 순환 참조가 감지 될 것이므로 언급해야합니다. 객체 $a 참조 $b$b 객체 참조 $a하고 더 이상 참조가 $a 또는 $b에이되지 않도록 경우 모두의 refcount1 수 있지만 그들은 여전히 ​​해제 (그리고 __destruct ED)됩니다. 이 경우 파괴의 순서는 정의되지 않은 행동이지만.

  • +3

    +1 참고 문헌에 대한 좋은 개관도 있습니다. – Xeoncross

    +2

    참고 : http://php.net/manual/en/features.gc.refcounting-basics.php – Herbert

    +1

    at-runtime 사용자 생성 함수 (create_function) 또는 eval 문의 실행 코드와 같은 것들을 사용할 때 쓰레기 컬렉션 재미 좀 얻을 수 있습니다. 예를 들면 다음과 같습니다. 클래스를 선언하고 eval 문 안에 소멸자가있는 메소드를 선언하면 해당 클래스의 전역 인스턴스를 만듭니다. 소멸자가 결코 호출되지 않는다는 것을 알 수 있습니다! 왜냐하면 소멸자 메서드가 호출되었을 때, 이미 평가가 종료 된 후에 가비지 수집에 의해 선택 되었기 때문에 함수가 더 이상 존재하지 않기 때문입니다. (이것은 문서화되지 않은 버그 일 수 있습니다.) –

    2

    정보는 다소 비밀이기는하지만 manual에 있습니다

    PHP 5는 C++와 같은 다른 객체 지향 언어에서와 유사한 개념을 가진 파괴자를 도입 하였다. 소멸자 메서드는 특정 객체에 대한 참조가 없거나 종료 시퀀스 중에 순서에 관계없이 호출됩니다.

    의미 : 객체가 파괴되면 (예 : unset()) 소멸자가 호출되거나 스크립트가 종료됩니다.

    추가 유용한 정보 : 생성자처럼

    는 부모 클래스의 파괴자는 엔진에 의해 명시 적으로 호출되지는 않을 것이다. 부모 소멸자를 실행하려면 소멸자 본문에서 parent :: __ destruct()를 명시 적으로 호출해야합니다.

    exit()를 사용하여 스크립트 실행을 중지하더라도 소멸자가 호출됩니다. 소멸자에서 exit()를 호출하면 나머지 종료 루틴이 실행되지 않습니다.

    +0

    내 예제의 경우, 소멸자는'$ foo' 때문에 스크립트가'MyPHPFunc'의 범위를 벗어날 때 호출됩니다 더 이상 접근 할 수 없습니까? –

    +0

    @ 짐 좋은 질문입니다, 그리고 대답은 - 나도 몰라!(하지만 코드 앞에'function'을 써야합니다. 그래서 여러분이 묻는 것이 명확합니다.) * 내 생각에 * 함수의 끝에서 파기 될 것입니다. 하나는 시도해야 할 것입니다. 나는 당신이 묻는 것에 답하지 않기 때문에이 대답을 제거하기를 원합니다. –

    4

    PHP 5는 C++과 같은 다른 객체 지향 언어에서와 유사한 개념을 가진 파괴자를 도입 하였다. 소멸자 메서드는 특정 객체에 대한 다른 참조가 없거나 종료 순서 중 임의의 순서로 호출되면 이 호출됩니다. - PHP Manual

    당신이 행동 과정을보고 싶다면, you can run this code here.

    1

    가장 좋은 방법은 테스트하는 것입니다.

    그러나 간단한 대답은 가비지 정리 중에 __destruct가 호출된다는 것입니다. 가비지 정리가 로컬 변수를 호출 할 수있는 범위가 없을 때이를 정리하는 진행중인 프로세스는 누구나 도움이되지 않는 거친 것입니다.

    그러나 여기에 몇 가지 샘플 코드, 그리고 완전히 스크립트로 내부적으로 범위를 종료 할 때 발생하는 설명 결과.

    <?php 
    class testingdestructor { 
        public function __construct($num) { 
         $this->num = $num; 
        } 
        public function __destruct() { 
         echo "I am number {$this->num}\n"; 
        } 
    } 
    class testing2{ 
        public function __construct($num) { 
         $this->classtest = new testingdestructor($num); 
        } 
        public function __destruct() { 
         echo "I am not a number\n"; 
        } 
    } 
    $iam1 = new testingdestructor(1); 
    $iam4 = new testing2(4); 
    function testfunction() { 
        $iam2 = new testingdestructor(2); 
    } 
    testfunction(); 
    $iam3 = new testingdestructor(3); 
    unset($iam1); 
    

    클래스 기능이 이상한 세트의 출력과 바르가 해제 마찬가지로,이 함수의 끝이 __destruct를 호출하는 것을 우리에게 보여줍니다이

    I am number 2 
    I am number 1 
    I am number 3 
    I am not a number 
    I am number 4 
    

    이며, 적어도 연습 스크립트 정리의 끝은 역순으로 작성됩니다.

    0

    클래스의 인스턴스를 생성하고 u는 소멸자를 호출하고 다시 u는 더 이상 사용할 수 있습니다 다른 작업을 수행하기 위해 다음 줄에 같은 개체를 사용하는 경우 모든 작업을 마무리 object.after를 사용하는 경우. 즉, 소멸자가 성공적으로 호출되었다는 의미입니다.

    관련 문제