使用内存引用比较 PHP 数组
是否可以查看两个数组变量是否指向同一内存位置? (它们是同一个数组)
Is it possible to see if two array variables point to the same memory location? (they are the same array)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
事实上,这是可以做到的。通过 php 扩展。
文件:config.m4
文件:php_test.h
文件:test.c
然后你所要做的就是 phpize 它,配置它,然后制作它。将“extension=/path/to/so/file/modules/test.so”添加到 php.ini 文件中。最后,重新启动 Web 服务器,以防万一。
返回(至少对我来说,你的内存地址可能会不同)
感谢Artefacto指出了这一点,但我的原始代码是按值传递数组,因此重新创建了包括引用数组在内的数组,并给你带来了糟糕的记忆价值观。此后我更改了代码以强制所有参数通过引用传递。这将允许引用、数组和对象不受 php 引擎干扰地传递。 $w/$z 是同一件事,但 $w/$x/$y 不是。旧代码实际上显示了引用损坏以及当传递所有变量与多次调用同一函数时内存地址会更改或匹配的事实。这是因为 PHP 在执行多个调用时会重用相同的内存。比较原始函数的结果是没有用的。新代码应该可以解决这个问题。
仅供参考 - 我正在使用 php 5.3.2。
Actually, this can be done. Through a php extension.
File: config.m4
File: php_test.h
File: test.c
Then all you have to do is phpize it, config it, and make it. Add a "extension=/path/to/so/file/modules/test.so" to your php.ini file. And finally, restart the web server, just in case.
Returns(at least for me, your memory addresses will probably be different)
Thanks to Artefacto for pointing this out, but my original code was passing the arrays by value, so thereby was recreating arrays including the referenced-one, and giving you bad memory values. I have since changed the code to force all params to be passed by reference. This will allow references, arrays, and object, to be passed in unmolested by the php engine. $w/$z are the same thing, but $w/$x/$y are not. The old code, actually showed the reference breakage and the fact that the memory addresses would change or match when all variables were passed in vs multiple calls to the same function. This was because PHP would reuse the same memory when doing multiple calls. Comparing the results of the original function would be useless. The new code should fix this problem.
FYI - I'm using php 5.3.2.
PHP 中的引用是通过不同名称访问相同变量内容的一种方法。它们不像 C 指针;例如,您不能使用它们执行指针算术,它们不是实际的内存地址, 等等。
结论:不,你不能
来自:http://www.php。 net/manual/en/language.references.whatare.php
References in PHP are a means to access the same variable content by different names. They are not like C pointers; for instance, you cannot perform pointer arithmetic using them, they are not actual memory addresses, and so on.
Conclusion: No, you can not
From: http://www.php.net/manual/en/language.references.whatare.php
你的问题实际上有点误导。 “指向相同的内存位置”和“是相同的数组”(对我来说意味着是引用,至少在 PHP 中)不是同一件事。
内存位置指的是指针。 PHP 中不提供指针。引用不是指针。
无论如何,如果您想检查
$b
实际上是否是$a
的引用,这是您可以获得的最接近实际答案的结果:Your question is actually a bit misleading. "point to the same memory location" and "are the same array" (which to me means is a reference to, at least in PHP) are not the same thing.
Memory locations refers to pointers. Pointers are not available in PHP. References are not pointers.
Anyway, if you want to check if
$b
is in fact a reference of$a
, this is the closest you can get to an actual answer:“check”函数在 2 分钟左右创建完成。它假设如果您更改引用的值,第二个引用也将具有新添加的值。
此函数仅适用于变量。您可以将它用于常量值、函数返回(除非通过引用)等。
编辑:在测试过程中,我最初遇到了一些困惑。我不断重复使用相同的变量名称($a 和 $b),这导致所有条件均为“是”。原因如下:
为了纠正这个问题,我给了它们一个不同的名称:
编辑:为什么答案是“是”而不是“否”
PHP 不会通过脚本显示指针信息(也不会指针操作等) 。
但是,它确实允许使用引用运算符“&”来完成别名变量(引用)。
特征通常存在于指针中,这解释了普遍的混乱。
也就是说,指针不是别名。
然而,如果我们看到原来的问题,这个人想知道 $a 是否与 $b 相同,而不是在内存中找到 $a (或 $b)。前面的要求适用于引用和指针,而后面的要求仅适用于指针。
The function "check" was created in 2 mins or so. It assumes that if you change a reference's value, a second reference would have the newly add value as well.
This function works on variables only. You can use it against constant value, function returns (unless by reference) etc.
Edit: During testing, I had some initial confusion. I kept reusing the same variable names ($a and $b) which resulted in all the conditionals being "yes". Here's why:
To correct the issue, I gave them a different name:
Edit: Why the answer is "yes" and not "no"
PHP does not reveal pointer information through scripting (neither pointer manipulation etc).
However, it does allow alias variables (references), done by using the reference operator '&'.
Feature is typically found in pointers, which explains the general confusion.
That said, pointers are not aliases.
However, if we see the original question, the person wanted to know if $a is the same as $b, not where in the memory $a (or $b) is found. Whereas the earlier requirement applies to both references and pointers, the later one only applies to pointers.
首先,你的问题含糊不清。它可能意味着几个不同的事情:
===
。$a
和$b
,如果我更改$a
,它会更改$b
>?第二个答案的答案并不容易确定。杰里米·沃尔顿(Jeremy Walton)的答案有一个重要的问题——他的函数按值接收,因此如果你向它传递一个引用,你就会强制分离并获得一个新的临时值的地址。您可以使函数通过引用接收参数,但是这样您就会遇到相反的问题 - 如果您传递一个值(引用计数 >= 2),您也会强制分离。
更重要的是,第二个问题是一个无关紧要的内部细节。考虑以下脚本:
所以重要的问题是第三个问题。不幸的是,没有直接的方法来确定这一点。这已被多次要求;例如,请参阅此请求。
但是,有几个选项:
xdebug_debug_zval
比有缺陷的debug_zval_dump
。这是在EG(active_symbol_table)
中对简单变量的简单查找(但如果您想包含对象属性和尺寸等,则会变得更加复杂),这也将允许您实现以下解决方案:第二个问题。First, your question is vague. It can mean several different things:
===
.$a
and$b
, if I change$a
, will it change$b
?The answer to the second answer is not easy to determine. Jeremy Walton's answer has one significant problem -- his function receives by value, so if you pass it a reference, you force a separation and get the address of a new temporary value. You could make the function receive the parameter by reference, but then you'd have the opposite problem -- if you passed a value (with refcount >= 2), you would also force a separation.
More importantly, the second question is an irrelevant internal detail. Consider the following script:
So the important question is the third one. Unfortunately, there is no straightforward way to determine this. This has been requested several times; see e.g. this request.
However, there are a few options:
xdebug_debug_zval
much more interesting than the flaweddebug_zval_dump
. This is a simple lookup inEG(active_symbol_table)
for simple variables (but would get more complex if you wanted to include object properties and dimensions etc.), and this would also allow you to implement a solution for the 2nd question.PHP 中的参考比较
我知道这个问题已经很老了,但这仍然相关 - 这就是我最终来到这里的原因。可能有多种方法可以对此进行测试,但我想出了其他几种方法。
PHP 7.4 引用相等性测试
ReflectionReference 为数组元素提供引用 id:
PHP 版本 5、7 和 8
该函数将依靠 PHP 序列化检测循环引用的事实来发现实际引用。缺点是对于大数组,它会暂时需要内存和时间来序列化数据。对于大数组,最好使用下面的实用数组相等性测试。
内存友好的 PHP < 7.4 数组引用检查
这个测试应该在不浪费太多内存的情况下完成任务。一个副作用是 PHP 使用写时复制来节省数组内存 - 因此当此函数追加到数组时,它将触发该机制。
Reference comparison in PHP
I know the question is old, but this is still relevant - which is why I ended up here. There are probably several ways to test this, but I came up with a couple of other methods.
PHP 7.4 reference equality test
ReflectionReference provides a reference id for array elements:
PHP version 5, 7 and 8
This function will spot an actual reference, by relying on the fact that PHP serialization detects circular references. The downside is that for big arrays it will temporary need memory and time to serialize the data. For big arrays it may be better to use the pragmatic array equality test below.
Memory friendly PHP < 7.4 array reference checking
This test should do the deed without wasting too much memory. A side effect is that PHP uses copy-on-write to save memory on arrays - so when this function appends to the array, it will trigger that mechanism.
这是未经测试的,但据我所知,php,变量在加载到系统中时被添加到全局变量中,因此它们相同的第一次出现应该是原始变量,但如果你有 2 个变量完全相同我'我不确定它会如何反应
This is untested but what i know of php, vars are added to the GLOBALS as they are are loaded into the system, so the first occurance where they are identical should be the original var, but if you have 2 Variables Exactly the same i'm not sure how it would react