PHP中Array的引用、值类型

乌龟壳 发布于 2016/08/22 17:47
阅读 794
收藏 1
PHP

一直以为PHP的Array是引用类型,直到我今天发现:

<?php

$a = array();
$k = $a;
$a['b'] = 'c';
var_dump($a);
var_dump($k);

居然结果是

array(1) {
  ["b"]=>
  string(1) "c"
}
array(0) {
}

不知道PHP为什么要这么设计

以下是问题补充:

@乌龟壳:经过查资料等,我总结出了一些东西,请关注的童鞋移驾http://my.oschina.net/visualgui823/blog/736848 (2016/08/23 20:32)
加载中
1
Narky
Narky

其实不完全是

php对array的处理分两步,$k = $a 的时候,内部真的只是用指针引用了一下

而当你$a['b'] ='c'的时候,才真正的拷贝一份,此时是变成值拷贝了。

也就是说如果只是简单的赋值,那还是引用类型,直到你改变其中一个数组的元素值,才是值类型。

这样做法的好处就是避免仅仅是赋值很大的数组时占用多份内存

leo108
leo108
直接回复copy on write就好了
1
超爱fitnesse
超爱fitnesse

要引用,就是用&

php> $a = array();

php> $k = &$a;
php> $a['b'] = 'c';
php> var_dump($a);
array(1) {
  'b' =>
  string(1) "c"
}
php> var_dump($k);
array(1) {
  'b' =>
  string(1) "c"
}
0
宏哥
宏哥

引用来自“Narky”的评论

其实不完全是

php对array的处理分两步,$k = $a 的时候,内部真的只是用指针引用了一下

而当你$a['b'] ='c'的时候,才真正的拷贝一份,此时是变成值拷贝了。

也就是说如果只是简单的赋值,那还是引用类型,直到你改变其中一个数组的元素值,才是值类型。

这样做法的好处就是避免仅仅是赋值很大的数组时占用多份内存

数组相当于 C语言当中的 指针数组

PHP的数组实际上只存放指针

而数据本身 被引用而且计入引用数量

这是为了效率

数组的拷贝必须做显式拷贝

Narky
Narky
基本上就是这样,都是指针操作,拷贝值,重新指过去
0
eechen
eechen
因为PHP支持显式&声明引用赋值呀,而且PHP数组是"写时复制".
echo round(memory_get_usage()/(1024*1024))."MB\n"; //0MB
$a = file('/home/eechen/note.txt', FILE_IGNORE_NEW_LINES);
echo round(memory_get_usage()/(1024*1024))."MB\n"; //9MB
$b = $a;
echo round(memory_get_usage()/(1024*1024))."MB\n"; //9MB(赋值后内存没有变化)
$b['new'] = 'element';
echo round(memory_get_usage()/(1024*1024))."MB\n"; //14MB(修改后内存发生变化,即写时复制)

JS:
var a = {"Client":"jQuery","Server":"PHP"};
var b = a;
a["New"] = "Element";
console.log(b);
//输出 Object { Client="jQuery",  Server="PHP",  New="Element"}

PHP例程1:
$a = array('Client'=>'jQuery','Server'=>'PHP');
$b = $a;
$a['New'] = 'Element';
var_export($b);
//输出 array('Client'=>'jQuery','Server'=>'PHP')

PHP例程2:
$a = array('Client'=>'jQuery','Server'=>'PHP');
$b = &$a; //引用赋值
$a['New'] = 'Element';
var_export($b);
//输出 array('Client'=>'jQuery','Server'=>'PHP','New'=>'Element')

JS中赋值时,原始类型(比如字符串)是复制值,引用类型(比如关联数组)是复制引用.
var a = {"Client":"jQuery","Server":"PHP"};
var b = JSON.stringify(a); //转成字符串后赋值
a["New"] = "Element";
console.log(JSON.parse(b)); //使用时转回关联数组(对象)
//输出 Object { Client="jQuery",  Server="PHP"}

IE8不支持JSON.parse和JSON.stringify,需要引入json2.js:
http://www.json.org/js.html
https://github.com/douglascrockford/JSON-js/blob/master/json2.js
IE9以下版本:
<!--[if lt IE 9]><script src="json2.js"></script><![endif]-->

感觉JS数组反而没有PHP的灵活性.
PHP果真是世界上最好的关联数组操作语言.
Narky
Narky
回复 @eechen : 请看我上面的回复,如果你不能理解的话,我也没什么好说的
eechen
eechen
回复 @Narky : 你先回答我JS支不支持关联数组,哈哈.
Narky
Narky
回复 @eechen : 还狂笑。。。能搞点实际的吗,别间歇性精神病发作。拿出证据来。SB
eechen
eechen
回复 @Narky : 煞笔你的意思是JS不支持关联数组么?狂笑!
Narky
Narky
回复 @eechen : 不要混淆概念,关联数组是map或者dictionary,请给出官方文档(注意,是官方)上说javascript的Object是associative array的证据。请不要拷贝多年前生造的蹩脚翻译来说明自己多理解js或者php。还有,如果关联数组是数组的话,那鲸鱼也是鱼喽?SB
下一页
0
inuxor
inuxor
如果只是引用,php武功得废一半
0
乌龟壳
乌龟壳

引用来自“inuxor”的评论

如果只是引用,php武功得废一半
愿闻其详
eechen
eechen
回复 @乌龟壳 : IE8还不支持stringify和parse这些JSON函数,还得引入JSON库,悲剧呀.PHP关联数组吊打JS没商量.
乌龟壳
乌龟壳
回复 @eechen : 亲,这是deepcopy,转成json要么是为了通讯(序列化),要么只是懒得自己实现deepcopy,用这种低效的方式转。
eechen
eechen
因为PHP这样的设计好理解呀.你看JS里真正复制个关联数组还得转成字符串,没法跟PHP写时复制数组+显式&引用比呀.
返回顶部
顶部