2011-12-15 11 views
14

मान लें कि हमारे पास कक्षा CFoo है। निम्नलिखित उदाहरण में CFoo::__destruct() कहलाता है?क्या निर्धारित करता है कि PHP में कक्षा ऑब्जेक्ट कब नष्ट हो जाता है?

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

    . . . 

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

इस उदाहरण में नाशक जब स्क्रिप्ट की MyPHPFunc क्योंकि $foo अब सुलभ हो जाएगा दायरे से बाहर होते ही कहा जाता है?

+0

कहा जाता है जब स्क्रिप्ट समाप्त हो जाती है (शट डाउन अनुक्रम के दौरान)। –

+5

पहले स्रोत पर जाएं: php manual .. उद्धरण: "विनाशक विधि को जल्द से जल्द कहा जाएगा जैसे किसी विशेष वस्तु के लिए कोई अन्य संदर्भ नहीं है, या शट डाउन अनुक्रम के दौरान किसी भी क्रम में" तो जब आप इसका उपयोग नहीं करेंगे या लिपि समाप्त होती है/यह मारे जाती है। http://www.php.net/manual/en/language.oop5.decon.php – mishu

उत्तर

33

PHP में सभी मान तथाकथित zval एस में सहेजे गए हैं। उन zval में वास्तविक डेटा, जानकारी टाइप करें और - यह आपके प्रश्न के लिए महत्वपूर्ण है - एक संदर्भ गणना। जैसे ही refcount0zval मुक्त हो जाता है पहुँचता है और वस्तु नाशक कहा जाता है

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

: निम्नलिखित स्निपेट पर एक नज़र डालें।

  • unset एक चर ing:

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

    लेकिन:

    $a = new B; // refcount=1 
    $b = $a; // refcount=2 
    unset($a); // refcount=1 => no destruct as refcount > 0, even though unset() was called! 
    
  • समारोह (या विधि) गुंजाइश छोड़ने

    यहाँ refcount तक पहुँचने 0 के कुछ उदाहरण हैं

    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 नहीं कर रहे हैं दोनों के refcount रों 1 हो जाएगा, लेकिन वे अभी भी मुक्त हो जाएगा (और __destruct ईडी)। इस मामले में हालांकि विनाश का आदेश अपरिभाषित व्यवहार है।

+3

+1 संदर्भों का अच्छा अवलोकन भी करते हैं। – Xeoncross

+2

यह भी देखें: http://php.net/manual/en/features.gc.refcounting-basics.php – Herbert

+1

यह भी ध्यान दें कि ऑन-रनटाइम उपयोगकर्ता जैसे कार्यों का उपयोग करते समय फ़ंक्शन (create_function) या एक eval कथन के अंदर कोड चलाना कचरा संग्रह थोड़ा मजाकिया हो सकता है। उदाहरण के लिए: यदि आप एक वर्ग घोषित करते हैं और इस तरह एक विध्वंस कथन के अंदर अपनी विधियों (एक विनाशक के साथ) घोषित करते हैं, तो उस वर्ग का वैश्विक उदाहरण बनाएं। आप देखेंगे कि विनाशक कभी नहीं बुलाया जाता है! Thats क्योंकि जब विनाशक विधि कहा जाएगा, eval बाहर निकलने के बाद इसे पहले से ही कचरा संग्रह द्वारा उठाया गया था, तो समारोह अब मौजूद नहीं है। (यह एक अनियंत्रित बग हो सकता है) –

2

जानकारी, manual में है कुछ हद तक गुप्त यद्यपि:

PHP 5 एक नाशक अवधारणा इस तरह के सी ++ के रूप में अन्य वस्तु उन्मुख भाषाओं, के समान परिचय देता है। विनाशक विधि को जल्द से जल्द बुलाया जाएगा क्योंकि किसी विशेष वस्तु के लिए कोई अन्य संदर्भ नहीं है, या शट डाउन अनुक्रम के दौरान किसी भी क्रम में।

अर्थ: ऑब्जेक्ट नष्ट होने पर विनाशक को बुलाया जाएगा (= उदा। unset()), या जब स्क्रिप्ट बंद हो जाती है।

अतिरिक्त उपयोगी जानकारी:

कंस्ट्रक्टर्स की तरह, माता-पिता विनाशकर्ता परोक्ष इंजन से बुलाया नहीं किया जाएगा। एक अभिभावक विनाशक को चलाने के लिए, किसी को विनाशक शरीर में स्पष्ट रूप से अभिभावक :: __ destruct() को कॉल करना होगा।

विनाशक को बाहर निकलने के लिए स्क्रिप्ट निष्पादन रोक दिया गया है, भले ही विनाशक को बुलाया जाएगा। एक विनाशक में कॉलिंग निकास() शेष शटडाउन दिनचर्या निष्पादित करने से रोक देगा।

+0

तो, मेरे उदाहरण के मामले में विनाशक को बुलाया जाएगा जब स्क्रिप्ट 'MyPHPFunc' के दायरे से बाहर निकलती है क्योंकि '$ foo' अब सुलभ नहीं होगा? –

+0

@ जिम यह एक अच्छा सवाल है, और जवाब है - मुझे नहीं पता!(हालांकि आपको अपने कोड के सामने 'फ़ंक्शन' लिखना चाहिए, इसलिए यह स्पष्ट है कि आप क्या पूछ रहे हैं।) मेरा * अनुमान * यह होगा कि यह फ़ंक्शन के अंत में नष्ट हो जाएगा - किसी को भी कोशिश करनी होगी। मैं इस जवाब को हटाने का लुत्फ उठा रहा हूं क्योंकि यह जवाब नहीं देता है कि आप –

4

PHP 5 एक नाशक अवधारणा इस तरह के सी ++ के रूप में अन्य वस्तु उन्मुख भाषाओं, के समान परिचय देता है। विनाशक विधि होगी जैसे ही किसी विशेष ऑब्जेक्ट, या शट डाउन अनुक्रम के दौरान किसी भी क्रम में कोई अन्य संदर्भ नहीं है। - PHP Manual

आप कार्रवाई में प्रक्रिया को देखने के लिए चाहते हैं, you can run this code here

<?php 

class A 
{ 
    public function __construct() { var_dump('Creating: '. get_class($this)); } 
    public function __destruct() { var_dump('Removing: '. get_class($this)); } 
} 

class B extends A {} 

$A = new A(); 

/* 
* When this block is called later on 
*/ 
function create_b() 
{ 
    $B = new B(); 
} // At this point the function scope ends, and since $B is not referenced anymore it's removed. 


var_dump('B is next'); 
create_b(); // Run above block, create, then destroy be 
var_dump('B is now gone'); 

// At this point the PHP file parser ends, $A is destroyed since it's not used anymore 
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); 

कक्षाएं समारोह की यह अजीब सेट के उत्पादन और वार्स इस

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

यह हमें पता चलता है कि समारोह के अंत __destruct कॉल के रूप में सेट नहीं करता है, और कहा कि कम से कम व्यवहार में स्क्रिप्ट क्लीनअप का अंत बनाया गया रिवर्स ऑर्डर में किया जाता है।

0

यदि कक्षा का उदाहरण बनाते हैं और ऑब्जेक्ट का उपयोग करते हैं। तो यदि आप विनाशक को कॉल करते हैं और फिर किसी अन्य कार्य को करने के लिए अगली पंक्ति में उसी ऑब्जेक्ट का उपयोग करते हैं तो आप अपने सभी कार्यों को पूरा कर सकते हैं, अब आप इसका उपयोग करने में सक्षम नहीं होंगे। इसका मतलब है कि आपके विनाशक को सफलतापूर्वक

संबंधित मुद्दे