【问题标题】:How can I get the address of an array?如何获取数组的地址?
【发布时间】:2023-03-08 19:57:01
【问题描述】:

我是 C++/Python/Java 的 PHP 新用户。在PHP中,有一个内置的数组类型,当我插入一个新对象或旧对象的副本后,如何证明该数组是同一个数组?在 C++/Python/Java 中,我可以使用对象地址、id() 或 hashcode 来测试对象是否相同,如何在 PHP 中进行相同的测试?

<?php
    $a['0'] = "a";
    $a['1'] = 'b'; //here, $a is a new copied one or just a reference to the old?
?>

好的,我更新我的问题,实际上,没有具体问题。我只想知道数组对象在插入新值之前和之后是否保持不变。 在 Python 中,我可以进行这样的测试:

a = [1]

print id(a)
a.append(2)
print id(a)

顺便说一句,这是 Python 中的 id() 函数手册。

id(...)
    id(object) -> integer

    Return the identity of an object.  This is guaranteed to be unique among
    simultaneously existing objects.  (Hint: it's the object's memory address.)

代码更新:

 # -*- coding: utf-8 -*-

a = [1, 2, 3]
b = [1, 2, 3]

print id(a)
print id(b)  //the id(b) is not same as id(a), so a and b has same content, but they both own their own values in the memory

c = a  // c is a reference to a 
c.append(4)
print c
print a  //after appending a new value(which means insert a new value to array), a has same value as c

所以问题是我可以通过 C++/Python/Java 中的代码来证明内存布局,我想确定我是否可以在 PHP 中做同样的事情。

【问题讨论】:

  • 你需要解决什么问题?您的代码没有给出太多提示......当您将元素附加到 C++ 时,它会创建一个全新的数组,这听起来很奇怪:-?
  • 我对C++/python/Java一无所知,但是在php中添加新元素时数组是一样的。
  • PHP 没有任何这样的机制。您必须描述您要解决的问题,以便我们建议在 PHP 中解决问题的适当方法。
  • @Epodax 是的,OP 似乎担心 数组 可能出于某种原因变成一个新实例。我认为在 PHP 中担心这是错误的事情。
  • @python 关于你所有的 Python 示例:如果你在 PHP 中做同样的事情,你的数组 不同。 $c = $a 将创建一个新的数组副本/实例。无需证明,这是给定的。

标签: php


【解决方案1】:

默认情况下,在 PHP 中只有对象是通过引用分配的。其他所有内容(包括数组)都是按值分配的。让两个变量指向同一个数组的唯一方法是使用 &amp; 运算符显式设置引用。 References Explained 章节对该主题进行了很好的概述。

对于对象,您可以相当容易地发现引用,即使是简单的var_dump()

$a = new DateTime;
$b = $a;
$c = clone $a;
var_dump($a, $b, $c);
object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2016-03-29 10:18:28.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Madrid"
}
object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2016-03-29 10:18:28.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Madrid"
}
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "2016-03-29 10:18:28.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Madrid"
}

请注意$a$b 共享的#1 标识符。

与其他类型根本不是微不足道的。在上述章节的Spotting References 部分中,有一个user comment 包含一些您可能想要检查的复杂代码,尽管它已经很旧了。

【讨论】:

    【解决方案2】:

    是的,当您修改其内容时,该数组仍然是相同的“对象”(不是 PHP 所称的,而是概念上的)。副本(“软副本”,写时复制)仅在您制作时才制作

    • 将数组分配给另一个变量不使用引用 (=&amp;)
    • 将它传递给一个函数没有引用
    • return它来自一个函数没有参考

    (实际上是一回事:将其分配给另一个变量。)

    【讨论】:

    • 您希望在代码示例中具体说明什么?
    • 在 OP 的上下文中,您可以将您的语句与示例代码绑定。意味着任何人如何以编程方式检查您的语句?
    • 我想您可以使用转储底层 zval 结构的低级调试器函数,但是 PHP 中没有真正的用户区 API 可以执行此类操作/这不是 PHP 允许您访问的东西/PHP 明确隔离了您从这些细节(选择你最喜欢的陈述)。
    【解决方案3】:

    除了@Anant 发布的内容,请参阅PHP Reference Counting,其中说明了 PHP 的运行时引擎如何存储变量。

    您会看到,即使是数组成员也是可以被其他对象、数组和变量指向(引用)的引用。因此,在 C 或 Python 中的两个“相同”数组可能存在于内存中的两个不同位置,PHP 将分别存储指向各个值的引用。

    如果其中一个值被两个非引用变量指向,那么它将为更改的值创建一个新的引用,现在每个变量都指向不同的引用。这是Copy On Write 优化。

    StackExchange 编程的这篇文章也不错。第一个答案提供了更多好的链接:Why are array references rarely used

    【讨论】:

      猜你喜欢
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      相关资源
      最近更新 更多