php foreach 是传值还是传引用?

2016-07-10 17:55:12 +08:00
 gdtv

先感谢此网页给我的指导 http://www.netingcn.com/php-foreach-pass-value-reference.html 现在我得知: 如果数组里面存放的是普通类型的元素就是采用传值的方式,存放对象类型元素采用的方式为传地址。

代码:

$raw_arr = array(
    (object)(array('id' => 1, 'name' => 'name1')),
    (object)(array('id' => 2, 'name' => 'name2')),
);
foreach ($raw_arr as $value) {
    $new_value = $value; //这里也是引用???
    $new_value->name = $new_value->name  . '-modify';
}
print_r($raw_arr);

输出:

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [name] => name1-modify
        )

    [1] => stdClass Object
        (
            [id] => 2
            [name] => name2-modify
        )

)

我的问题: 我想在 foreach 循环内将$value 传值给一个新变量$new_value ,我希望对$new_value 的任何操作都不会影响原始数组$raw_arr, 请问该怎么做呢?

2786 次点击
所在节点    PHP
11 条回复
shyling
2016-07-10 19:07:52 +08:00
复制引用的形式。。
falcon05
2016-07-10 19:11:13 +08:00
clone
shiny
2016-07-10 19:20:04 +08:00
因为这个是 Object ,其他类型不受影响
moult
2016-07-10 21:12:05 +08:00
一般情况下,对象传引用,基本数据类型传值。
如果变量前面有取地址符&的话,那么基本数据类型也是传引用。
```
<?php
$list = array(1,2,3);
foreach($list as &$value){
$value = $value*2;
}
unset($value);
var_dump($list);
```

另外,友情提醒,变量记得 unset 掉,不然会有大彩蛋的。
moult
2016-07-10 21:16:39 +08:00
抱歉,回复的时候没有看仔细。
$new_value = clone $value;
但要任何操作都不会影响,还是得看这个 Object 实现了,__clone()魔法函数可以控制拷贝深度!
dawniii
2016-07-11 06:55:37 +08:00
@moult 话说大彩蛋是什么呢?
moult
2016-07-11 13:09:43 +08:00
@dawniii
在执行 foreach($array as &$item) 之后,如果$item 没有 unset 的话,那么$item 这个变量始终指向$array 的最后一个元素。
也就是如果下面编码的时候没注意,来了个$item='foo_bar'的话,那么 end($array)==='foo_bar',导致$array 内容离奇得不对!尤其是第一年工作的时候,遇到过好几次。。
所以 foreach 的时候,如果要修改源数组内容,尽量少用&,最好 foreach($array as $key=>$item)!
当然,如果 foreach 里面没有 break 场景的话,用 array_walk 更好。
gdtv
2016-07-11 13:23:22 +08:00
@moult 就算不用&,如果$array 的元素的类型是 object ,还是引用
szopen
2016-07-11 15:10:21 +08:00
在 PHP 7 foreach 默认是复制,详细变更见: https://wiki.php.net/rfc/php7_foreach
Balthild
2016-07-11 15:44:28 +08:00
这么说的话,假如$var1 是 Object ,那$var2 = $var1;实际上是把这个对象的地址给了 $var2 ,而不是复制了一个对象实例?
nec
2016-07-12 08:54:48 +08:00
如果要改变原数组的值,并且原数组不为对象数组(即为基本数据类型数组),那么就传引用

上代码:

$bk_cart_arr = ['1:1','2:1','3:2'];
$product_id = 1;
$count = 1;
foreach ($bk_cart_arr as &$value) { //传引用
//拿到数组中的每个字符串,并且使用 strpos ()来获取:的位置)
$index = strpos($value, ":");
if (substr($value, 0, $index) == $product_id) {
$count = ((int)substr($value, ($index + 1))) + 1;
$value = $product_id . ':' . $count;
break;
}
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/291532

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX