第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

重用的對(duì)象不會(huì)調(diào)用`__destruct`?

重用的對(duì)象不會(huì)調(diào)用`__destruct`?

PHP
湖上湖 2022-07-02 16:45:06
我試圖在 CLI 程序中創(chuàng)建一個(gè)類似“池”的結(jié)構(gòu),其中包括許多“借用”和“回收”。在測(cè)試的時(shí)候,我遇到了一些非常出乎意料的事情:<?phpclass FOO{    public static $pool=[];    public static function get()    {        if(empty(self::$pool))        {            self::$pool[]=new self(mt_rand(1000,9999));        }        return array_shift(self::$pool);    }    protected static function recycle(FOO $foo)    {        echo "Recycling {$foo->num}\n";        self::$pool[]=$foo;    }    public $num;    protected function __construct(int $num)    {        $this->num=$num;    }    public function __destruct()    {        static::recycle($this);    }}function Bar(){    $foo=FOO::get();    echo "Got {$foo->num}\n";}echo "Bar\n";Bar();echo "Bar\n";Bar();echo "Bar\n";Bar();echo "Bar\n";Bar();print_r(FOO::$pool);echo "End.\n";輸出是:BarGot 2911Recycling 2911BarGot 2911BarGot 1038Recycling 1038BarGot 1038Array()End.如果我將Bar()調(diào)用限制為 3 次而不是 4 次,我會(huì)得到以下輸出:BarGot 7278Recycling 7278BarGot 7278BarGot 6703Recycling 6703Array(    [0] => FOO Object        (            [num] => 6703        ))End.在這里你可以看到,當(dāng)一個(gè)對(duì)象被“重用”時(shí)(見(jiàn)例1中的2911和1038,例2中的7278),它__destruct()不會(huì)被調(diào)用;相反,它會(huì)簡(jiǎn)單地消失。我很困惑。為什么會(huì)發(fā)生這種情況?為什么FOO->__destruct每次都不叫?是否可以制作FOO自動(dòng)回收實(shí)例?我在 PHP-7.2 中對(duì)此進(jìn)行了測(cè)試,在 Windows 和 WSL-Ubuntu 中都觀察到了這種行為。
查看完整描述

1 回答

?
子衿沉夜

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊

據(jù)我所知,不會(huì)為同一個(gè)對(duì)象調(diào)用兩次析構(gòu)函數(shù)。重用析構(gòu)函數(shù)中的對(duì)象通常是一種不好的做法。調(diào)用析構(gòu)函數(shù)的對(duì)象應(yīng)該被銷毀,而不是重用。在您的測(cè)試腳本中它不會(huì)導(dǎo)致任何嚴(yán)重的問(wèn)題,但在現(xiàn)實(shí)生活中,如果開(kāi)發(fā)人員不小心,這種用法可能會(huì)導(dǎo)致意外行為。

起初,當(dāng)我閱讀您的問(wèn)題時(shí),我擔(dān)心您造成了內(nèi)存泄漏,但事實(shí)并非如此。Bar()僅當(dāng)尚未在此對(duì)象上調(diào)用析構(gòu)函數(shù)時(shí),才在離開(kāi)范圍時(shí)調(diào)用析構(gòu)函數(shù)。但是,由于您保存了引用并在垃圾收集器ref_count內(nèi)部增加了此對(duì)象的引用,__destruct()因此尚無(wú)法收集該對(duì)象。它必須等到下一次你減少ref_count這個(gè)對(duì)象的時(shí)候。

該過(guò)程可以解釋如下(簡(jiǎn)化):

  1. 您調(diào)用Bar()創(chuàng)建一個(gè)實(shí)例的函數(shù)FOO。一個(gè)對(duì)象被創(chuàng)建并分配給$foo。( ref_count = 1)

  2. 在結(jié)束時(shí)Bar()對(duì)該對(duì)象的唯一引用丟失(ref_count = 0),這意味著 PHP 開(kāi)始銷毀該對(duì)象的過(guò)程。
    2.1。析構(gòu)函數(shù)被調(diào)用。在析構(gòu)函數(shù)內(nèi)部,您將ref_count增加到 1。
    2.2。下一步將是 GC 收集對(duì)象,但ref_count不是零。在您的示例中,這可能意味著循環(huán)或類似,在析構(gòu)函數(shù)中創(chuàng)建了一個(gè)新引用。GC 必須等到?jīng)]有非循環(huán)引用才能收集對(duì)象。

  3. Bar()再打電話。您將同一個(gè)對(duì)象從靜態(tài)數(shù)組中移出,這意味著其中的引用FOO::$pool已經(jīng)消失,但您立即將其分配給$foo. ( ref_count = 1)

  4. 在結(jié)束時(shí)Bar()對(duì)該對(duì)象的唯一引用丟失(ref_count = 0),這意味著 GC 最終可以收集該對(duì)象。析構(gòu)函數(shù)已經(jīng)被調(diào)用了,所以這里不需要采取其他行動(dòng)。

你沒(méi)有回收對(duì)象,你只是延長(zhǎng)了它在內(nèi)存中的存在。您可以訪問(wèn)它一段時(shí)間,但對(duì)于 PHP,該對(duì)象已經(jīng)處于被銷毀的過(guò)程中。


查看完整回答
反對(duì) 回復(fù) 2022-07-02
  • 1 回答
  • 0 關(guān)注
  • 87 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)