如何销毁物体?


120

据我所知(很少),给出了两种方法:

$var = new object()

然后:

// Method 1: Set to null
$var = null;
// Method 2: Unset 
unset($var); 

其他更好的方法?我在这里劈头发吗?

Answers:


152

您正在寻找unset()

但是要考虑到您不能显式销毁对象。

它会保留在那里,但是如果您取消设置对象,并且脚本将PHP推入内存限制,则不需要的对象将被垃圾回收。我会选择unset()(而不是将其设置为null),因为它似乎具有更好的性能(未经测试,但已记录在PHP官方手册的注释中)。

也就是说,请记住,PHP总是在提供页面后立即销毁对象。因此,仅在非常长的循环和/或密集的页面上才需要这样做。


1
弗兰基(Frankie),我来自C ++,当我们使用new一次时,则必须使用delete一次。在PHP中不是这样吗?当不再需要该对象时,会自动进行垃圾回收?
gsamaras 2015年

3
@gsamaras是的。但是,您也可能会泄漏,如果正在执行守护程序或类似操作,则应阅读有关php GC的更多信息。在大多数站点中,请求的生存期很短,所以没有关系。php.net/manual/en/features.gc.refcounting-basics.php
弗兰基(Frankie)

是否unset()删除对对象的引用?
Yousha Aleayoub

9

一个方便的帖子,解释了对此的一些误解:

不要显式调用析构函数

这涵盖了关于析构函数如何工作的一些误解。根据PHP5文档,显式调用它实际上不会破坏您的变量:

PHP 5引入了与其他面向对象的语言(例如C ++)相似的析构函数概念。一旦没有其他对特定对象的引用,或者在关闭序列期间以任何顺序,将调用析构函数方法。

上面的文章确实指出,在其他情况下,只要没有其他指向已分配的内存,就可以将变量设置为null。


2

简短的回答:两者都需要。

我觉得给出了正确的答案,但很少。是的,一般来说,unset()最适合“速度”,但是如果您想立即回收内存(以CPU为代价),则应该使用null。

就像其他提到的一样,设置为null并不意味着所有内容都会被回收,您可以拥有共享内存(非克隆)对象,以防止破坏该对象。而且,就像其他人所说的那样,您无论如何都不能明确地“销毁”对象,因此您无论如何都不要这样做。

您将需要找出最适合您的。您也可以对将要使用unset或null调用的对象使用__destruct(),但应谨慎使用,就像其他人所说的那样,切勿直接调用!

看到:

http://www.stoimen.com/blog/2011/11/14/php-dont-call-the-destructor-explicitly/

分配NULL和未设置之间有什么区别?


0

这是简单的证明,您无法销毁对象,只能销毁指向该对象的链接。

$var = (object)['a'=>1];
$var2 = $var;
$var2->a = 2;
unset($var2);
echo $var->a;

退货

2

在此处查看其运行情况:https : //eval.in/1054130


3
正确,您已销毁$var2了对的引用$var。现在您也销毁$var了该对象,并且假设没有其他引用保留在该对象上,那么您就可以完成。
i336_

4
您不是在破坏对象,而是在破坏指向该对象的指针。这是一个很大的区别。
Yevgeniy Afanasyev

1
在其他语言中,您可以销毁一个对象,所有其他指针将为您提供异常或垃圾,但是php并非如此
Yevgeniy Afanasyev

1
你无法摧毁。如果没有保存该对象的引用,则该对象已准备好由垃圾收集器收集。而且您不能强制运行垃圾收集器。
丹尼尔(Daniel)

0

可能是在创建新的mysqli对象的情况下。

$MyConnection = new mysqli($hn, $un, $pw, $db);

但是即使关闭对象

$MyConnection->close();

如果使用print_r()来检查的内容$MyConnection,则会出现以下错误:

Error:
mysqli Object

Warning: print_r(): Property access is not allowed yet in /path/to/program on line ..
( [affected_rows] => [client_info] => [client_version] =>.................)

在这种情况下,您将无法使用,unlink()因为unlink()它将需要一个路径名字符串,但在这种情况下,它$MyConnection是一个对象。

因此,您还有另一种选择将其值设置为null:

$MyConnection = null;

现在一切顺利,正如您所期望的。您没有任何内容在变量内$MyConnection,并且您已经清理了mysqli对象。

建议您先关闭对象,然后再将变量的值设置为null


-7

我会选择unset,因为它可能会给垃圾收集器提供更好的提示,以便可以更快地再次使用内存。请注意,该对象指向的任何东西要么具有其他引用,要么首先被取消设置,否则您实际上必须等待垃圾收集器,因为那时将没有它们的句柄。


16
除非您确实有资料来备份您的答案,否则您可能不应该发布您认为“可能”发生的事情。它没有用,并且导致这种错误信息被当作真相重复。
meagar

1
@meagar正是我链接到官方手册页的确切原因,在该手册页的注释中,有一个将unset()与null进行比较的示例测试。
弗兰基(Frankie)2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.