国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

__destruct與register_shutdown_function執(zhí)行的先后順序問題

2019-11-15 01:51:31
字體:
供稿:網(wǎng)友
__destruct與register_shutdown_function執(zhí)行的先后順序問題

根據(jù)php手冊(cè)的解析。

__destruct是

析構(gòu)函數(shù)會(huì)在到某個(gè)對(duì)象的所有引用都被刪除或者當(dāng)對(duì)象被顯式銷毀時(shí)執(zhí)行。

而register_shutdown_function是

Registers a callback to be executed after script execution finishes or exit() is called. 注冊(cè)一個(gè)回調(diào)函數(shù),此函數(shù)在腳本運(yùn)行完畢或調(diào)用exit()時(shí)執(zhí)行。

從字面上理解,__destruct是對(duì)象層面的,而register_shutdown_function是整個(gè)腳本層面的,理應(yīng)register_shutdown_function的級(jí)別更高,其所注冊(cè)的函數(shù)也應(yīng)最后執(zhí)行。為證實(shí)我們的猜測,我們寫一段腳本:

register_shutdown_function(function(){echo 'global';});    class A {            public function __construct(){        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }              }    new A;

執(zhí)行結(jié)果:

A::__destruct global

完全證實(shí)了我們的猜測,它按照對(duì)象->腳本的順序被執(zhí)行了。

但如果我們?cè)趯?duì)象中注冊(cè)了register_shutdown_function呢?它還是一樣的順序嗎?!

class A {            public function __construct(){            register_shutdown_function(function(){echo 'local', '<br/>';});        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }                    }    new A;

結(jié)果:

local A::__destruct

可以看到register_shutdown_function先被調(diào)用了,最后才是執(zhí)行對(duì)象的__destruct。這表明register_shutdown_function注冊(cè)的函數(shù)被當(dāng)作類中的一個(gè)方法?!不得而知,這可能需要查看php源代碼才能解析了。

我們可以擴(kuò)大范圍查看情況:

register_shutdown_function(function(){echo 'global', '<br/>';});    class A {            public function __construct(){            register_shutdown_function(array($this, 'op'));
        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }                public function op()        {            echo __class__,'::',__function__,'<br/>';        }            }    class B {            public function __construct()        {            register_shutdown_function(array($this, 'op'));            $obj = new A;        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }                public function op()        {            echo __class__,'::',__function__,'<br/>';        }        }        $b = new B;

我們?cè)谌肿?cè)一個(gè)register_shutdown_function函數(shù),在類AB中又各注冊(cè)了一個(gè),而且類中分別還有析構(gòu)方法。最后運(yùn)行結(jié)果會(huì)怎樣呢?

global B::op A::op A::__destruct B::__destruct

結(jié)果完全顛覆了我們的想像,register_shutdown_function函數(shù)無論在類中注冊(cè)還是在全局注冊(cè),它都是先被執(zhí)行,類中執(zhí)行的順序就是它們被注冊(cè)的先后順序。如果我們?cè)僮屑?xì)研究,全局的register_shutdown_function函數(shù)無論放在前面還是后面都是這個(gè)結(jié)果,事情似乎有了結(jié)果,那就是register_shutdown_function比__destruct先執(zhí)行,全局的register_shutdown_function函數(shù)又先于類中注冊(cè)的register_shutdown_function先執(zhí)行。

且慢,我無法接受這個(gè)結(jié)果,按照這樣的結(jié)論,難道說腳本已經(jīng)結(jié)束后還可以再執(zhí)行__destruct?!因此,我還要繼續(xù)驗(yàn)證這個(gè)結(jié)論---去掉類中注冊(cè)register_shutdown_function,而保留全局register_shutdown_function:

class A {                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }     }    class B {            public function __construct()        {            $obj = new A;        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }       }        register_shutdown_function(function(){echo 'global', '<br/>';});

輸出:

A::__destruct global B::__destruct

結(jié)果令人茫然,A、B兩個(gè)類的析構(gòu)函數(shù)執(zhí)行順序無可質(zhì)疑,因?yàn)锽中調(diào)用了A,類A肯定比B先銷毀,但全局的register_shutdown_function函數(shù)又怎么夾在它們中間被執(zhí)行?!費(fèi)解。

按照手冊(cè)的解析,析構(gòu)函數(shù)也可在調(diào)用exit時(shí)執(zhí)行。

析構(gòu)函數(shù)即使在使用 exit()終止腳本運(yùn)行時(shí)也會(huì)被調(diào)用。在析構(gòu)函數(shù)中調(diào)用 exit() 將會(huì)中止其余關(guān)閉操作的運(yùn)行。

如果在函數(shù)中調(diào)用exit,它們又如何被調(diào)用的呢?

class A {            public function __construct(){            register_shutdown_function(array($this, 'op'));            exit;        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }                public function op()        {            echo __class__,'::',__function__,'<br/>';        }            }    class B {            public function __construct()        {            register_shutdown_function(array($this, 'op'));            $obj = new A;        }                public function __destruct()        {            echo __class__,'::',__function__,'<br/>';        }                public function op()        {            echo __class__,'::',__function__,'<br/>';        }        }        register_shutdown_function(function(){echo 'global', '<br/>';});        $b = new B;

輸出:

global B::op A::op B::__destruct A::__destruct

這個(gè)順序與上述第三個(gè)例子相似,不同的且令人不可思議的是B類的析構(gòu)函數(shù)先于類A執(zhí)行,難道銷毀B后類A的所有引用才被全部銷毀?!不得而知。

 

結(jié)論:
  • 1、盡量不要在腳本中將register_shutdown_function與__destruct混搭使用,它們的行為完全不可預(yù)測。
  • 1、因?yàn)閷?duì)象在相互引用,因此我們無法測知對(duì)象幾時(shí)被銷毀,當(dāng)需要按順序輸出內(nèi)容時(shí),不應(yīng)把內(nèi)容放在析構(gòu)函數(shù)__destruct里;
  • 2、盡量不要在類中注冊(cè)register_shutdown_function,因?yàn)樗捻樞螂y以預(yù)測(只有調(diào)用這個(gè)對(duì)象時(shí)才會(huì)注冊(cè)函數(shù)),而且__destruct完全可以代替register_shutdown_function;
  • 3、如果需要在腳本退出時(shí)執(zhí)行相關(guān)動(dòng)作,最好在腳本開始時(shí)注冊(cè)register_shutdown_function,并把所有動(dòng)作放在一個(gè)函數(shù)里。

敬請(qǐng)大家指正。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 隆子县| 曲靖市| 泰顺县| 吕梁市| 民勤县| 益阳市| 宜黄县| 察哈| 铁力市| 兴业县| 黄骅市| 丹东市| 凤城市| 五河县| 林西县| 印江| 会理县| 云安县| 彭山县| 临安市| 乐东| 建水县| 霍邱县| 海南省| 临江市| 年辖:市辖区| 辰溪县| 麻江县| 博客| 日喀则市| 凉山| 娄烦县| 股票| 兴义市| 仙游县| 盐亭县| 珠海市| 大竹县| 湾仔区| 阳高县| 育儿|