当一系列作为一个参数的方法或功能是通过参考?

什么这样做:

$a = array(1,2,3);
$b = $a;

$b 一个参考 $a?

有帮助吗?

解决方案

有关的问题的第二部分,请参阅手册的阵列页,其中规定的(引用)

  

阵列分配总是涉及值   复制。使用参考操作员   通过参考复制的阵列。

和给定的示例:

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2, 3)

$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>

,点击 对于第一部分,以确保最好的办法是设法; - )

考虑的码本示例:

function my_func($a) {
    $a[] = 30;
}

$arr = array(10, 20);
my_func($arr);
var_dump($arr);

它会给这样的输出:

array
  0 => int 10
  1 => int 20

其指示功能尚未改性这是作为一个参数传递的“外部”阵列:它是通过如一个副本,而不是参考

如果您想要通过引用传递,你就必须修改函数,这种方式:

function my_func(& $a) {
    $a[] = 30;
}

和输出将变为:

array
  0 => int 10
  1 => int 20
  2 => int 30

如,此时,该阵列已被“引用”传递。

,点击 不要犹豫,阅读引用的解释手册的部分:它应该回答大家的一些问题; - )

其他提示

使用关于第一个问题,阵列通过引用传递,除非它是在方法中修改/起作用你打电话。如果尝试修改方法/功能中的阵列,它的一个副本被首先进行,然后只拷贝被修改。这使得看起来好像阵列由值传递时在实际上它不是

例如,在第一种情况下,即使你没有定义你的函数接受$ my_array引用(通过使用参数定义&字符),它仍然被引用传递(即:你不”吨废物存储器用的不必要的复制)。

function handle_array($my_array) {  

    // ... read from but do not modify $my_array
    print_r($my_array);

    // ... $my_array effectively passed by reference since no copy is made
}

然而,如果在修改阵列,它的一个副本被首次提出(它使用更多的存储器,但是离开你的原始数组不受影响)。

function handle_array($my_array) {

    // ... modify $my_array
    $my_array[] = "New value";

    // ... $my_array effectively passed by value since requires local copy
}

FYI - 这被称为“懒复制”或“写入时复制”

TL; DR

a)所述方法/函数的只读取数组参数=>的隐式的(内部)参考结果 b)该方法/函数的修改数组参数=>的结果 c)该方法/函数数组参数被明确标记为基准(用符号)=>的明确的(用户的土地)参考

或者这样的:结果 - 的非符号阵列PARAM :通过引用传递;写操作改变的磁盘阵列的新副本,这是第一个写创建的副本;点击 - 的符号阵列PARAM :通过引用传递;在写操作改变原来的数组。

记住 - PHP确实值拷贝的你写应用于非符号阵列PARAM的时刻。这就是copy-on-write手段。我很想告诉你这种行为的C源代码,但它在那里是可怕的。更好地利用函数xdebug_debug_zval()

帕斯卡MARTIN是正确的。科斯塔康托斯是更是如此。

答案

这取决于

龙版本

我觉得我在写这下我自己。我应该有一个博客或东西...

每当人们谈论的引用(或指针,对于这个问题),他们通常在舌战结束了(只是看这个的螺纹!)。点击 PHP是一个古老的语言,我想我应该加起来混乱(即使上述答案的总结)。因为,虽然两个人可以就在同一时间,你最好只是破解他们的头连成一片的答案。

首先,你应该知道的你,如果你没有在黑与白的方式的回答是不是学究。事情是更复杂的不是“是/否”。

正如你所看到的,整个的价值/按引用的东西有很大关系到究竟什么是你用你的方法/函数范围数组做?读它或修改它。

什么PHP说没有? (又名 “改变明智”)

手册说此(重点煤矿):

  

默认情况下,函数的参数是值传递(使得如果   函数内的自变量的值是<强>改变下,它没有得到   改变了功能的外部)。以允许的修改一个函数将其   通过引用传递的参数,它们必须是

     

要具有参数传递给   功能总是通过引用传递,前面加上符号(&)到   在函数定义参数名称

据我所知,当大,严重的,诚实对上帝的程序员谈论引用,他们通常讲的改变该引用的价值。而这正是对手动会谈。hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"

还有,他们不提,但另一种情况:如果我不改变任何东西 - 只是看结果 如果你传递一个数组到不明确标志着一个参考的方法,我们不改变功能范围数组? E.g:

<?php
function readAndDoStuffWithAnArray($array) 
{
    return $array[0] + $array[1] + $array[2];
}

$x = array(1, 2, 3);

echo readAndDoStuffWithAnArray($x);

阅读,我的旅伴。

什么是PHP实际上呢? (又名 “存储器明智”)

同样大和严重的程序员,当他们得到更为严重,他们谈论关于引用“内存优化”。所以做PHP。因为PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting,这是为什么

这不会是理想的巨大的数组传递给各种功能,以及PHP,使它们的副本(这是“传递的价值”呢,毕竟):

<?php

// filling an array with 10000 elements of int 1
// let's say it grabs 3 mb from your RAM
$x = array_fill(0, 10000, 1); 

// pass by value, right? RIGHT?
function readArray($arr) { // <-- a new symbol (variable) gets created here
    echo count($arr); // let's just read the array
}

readArray($x);

好现在,这实际上是传递的价值,我们就会有一些3MB + RAM走了,因为有的数组的副本,对不对?

错误。只要我们不改变$arr变量,这是一个参考,请存储器逐即可。你刚才没有看到它。这就是为什么PHP 提到 用户土地引用谈论&$someVar时,内部和显式的(用符号)的人之间进行区分。

事实

所以,when an array is passed as an argument to a method or function is it passed by reference?

我想出的 3 (是,三个)的情况下:结果 a)所述方法/函数的只读取数组参数,点击 b)该方法/函数的修改数组参数,点击 c)该方法/函数数组参数被明确标记为基准(用符号)


首先,我们看到,数组实际上有多少内存吃(这里运行):

<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840

这许多字节。大。

a)所述方法/函数的只读取数组参数

现在让我们把其中的函数只读取的上述数组作为参数,我们将看到读逻辑多少内存占用:

<?php

function printUsedMemory($arr) 
{
    $start_memory = memory_get_usage();

    count($arr);       // read
    $x = $arr[0];      // read (+ minor assignment)
    $arr[0] - $arr[1]; // read

    echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}

$x = array_fill(0, 10000, 1); // this is 1331840 bytes
printUsedMemory($x);

想猜?我得到80! 看到自己。这是PHP手册忽略的部分。如果$arr PARAM实际上是通过按值,你会看到类似1331840字节的东西。看来,$arr就像一个参考,不是吗?这是因为它的一个引用 - 一个内部。

b)该方法/函数的修改数组参数

现在,让我们的,以param所,而不是从它读取:

<?php

function printUsedMemory($arr)
{
    $start_memory = memory_get_usage();

    $arr[0] = 1; // WRITE!

    echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}

$x = array_fill(0, 10000, 1);
printUsedMemory($x);

再次看到自己,但对我来说,那是相当接近这个所以是1331840.情况下,该阵列的实际上被复制到$arr

c)该方法/函数数组参数被明确标记为基准(用符号)

现在让我们看看有多少内存的的写操作,以明确提及的取值(运行这里) - 注意,函数签名与号:

<?php

function printUsedMemory(&$arr) // <----- explicit, user-land, pass-by-reference
{
    $start_memory = memory_get_usage();

    $arr[0] = 1; // WRITE!

    echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}

$x = array_fill(0, 10000, 1);
printUsedMemory($x);

我敢打赌,你会得到200最大!因此,这约吃尽可能多的内存的从非符号PARAM读取

通过默认

  1. 元是通过价值。不可能Java,string是原始在PHP
  2. 阵列原语传递的价值
  3. 对象是过去了 参考
  4. 阵列的目的是通过价值(阵列),但每个目的是通过参考。

    <?php
    $obj=new stdClass();
    $obj->field='world';
    
    $original=array($obj);
    
    
    function example($hello) {
        $hello[0]->field='mundo'; // change will be applied in $original
        $hello[1]=new stdClass(); // change will not be applied in $original
        $
    }
    
    example($original);
    
    var_dump($original);
    // array(1) { [0]=> object(stdClass)#1 (1) { ["field"]=> string(5) "mundo" } } 
    

注:作为一个优化的,每一个值是通过为参考,直至其修改内部的功能。如果这是修改的和价值通过了准则,这是复制和复制是修改。

当一个阵列被传递到在PHP方法或函数,它是由值来传递,除非你明确地传递它通过引用,像这样:

function test(&$array) {
    $array['new'] = 'hey';
}

$a = $array(1,2,3);
// prints [0=>1,1=>2,2=>3]
var_dump($a);
test($a);
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);

在第二个问题,$b不是参照$a,但$a的副本。

就像第一示例中,可以通过执行参考$a以下内容:

$a = array(1,2,3);
$b = &$a;
// prints [0=>1,1=>2,2=>3]
var_dump($b);
$b['new'] = 'hey';
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);

这线程是有点老,但这里的东西我只是碰到:

试试这个代码:

$date = new DateTime();
$arr = ['date' => $date];

echo $date->format('Ymd') . '<br>';
mytest($arr);
echo $date->format('Ymd') . '<br>';

function mytest($params = []) {
    if (isset($params['date'])) {
        $params['date']->add(new DateInterval('P1D'));
    }
}

http://codepad.viper-7.com/gwPYMw

请注意没有的放大器用于到$ params参数和仍然它改变了$ ARR [“日期”]的值。这并没有真正匹配所有在这里的其他解释什么,我觉得到现在为止。

如果我克隆到$ params [“日期”]目的,第二输出日期保持不变。如果我只是它设置为一个字符串它不影响输出任一

在PHP阵列被传递给函数值通过默认,除非明确通过引用传递它们,如下面的片断所示:

$foo = array(11, 22, 33);

function hello($fooarg) {
  $fooarg[0] = 99;
}

function world(&$fooarg) {
  $fooarg[0] = 66;
}

hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value

world($foo);
var_dump($foo); // (original array modified) array passed-by-reference

下面是输出:

array(3) {
  [0]=>
  int(11)
  [1]=>
  int(22)
  [2]=>
  int(33)
}
array(3) {
  [0]=>
  int(66)
  [1]=>
  int(22)
  [2]=>
  int(33)
}

要延伸的答案,也多维数组由值被传递的子阵列中的一个,除非明确地参考传递。

<?php
$foo = array( array(1,2,3), 22, 33);

function hello($fooarg) {
  $fooarg[0][0] = 99;
}

function world(&$fooarg) {
  $fooarg[0][0] = 66;
}

hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value

world($foo);
var_dump($foo); // (original array modified) array passed-by-reference

其结果是:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  [1]=>
  int(22)
  [2]=>
  int(33)
}
array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(66)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  [1]=>
  int(22)
  [2]=>
  int(33)
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top