PHP——4(PHP赋值行为)

PHP——2(PHP变量作用域)
PHP——3(PHP变量分离/引用(Variables Separation))
为辅助阅读,可直接跳过

Laruence关于引用赋值行为的描述和用debug_zval_dump刺探的结果有出入,下面我会指出Laruence的叙述有误的地方。
总结来说,分析PHP赋值行为遵循以下原则:
在保证常规赋值思维的前提下,保证占用尽量小的内存和做尽量少的指针指向变化。

1.内存的问题("Copy on write")
由于PHP弱类型变量的原因,在PHP中存储一个变量会比在C等强类型语言中占用的内存大得多,如果也按照C语言中每个变量开辟一个单独的内存空间来保存,显然将占用大量的内存空间,显然这并不是最优化的设计。我们自己可以设想一下在PHP中诸如以下的赋值语句

<?php  
$a=1;  
$b=$a;  
?>  

对$a显然要开辟一块新的内存,但是对于$b来说要不要开辟新的内存呢?
显然,在PHP中我们是不需要像C一样,每次都去开辟变量内存的,针对上面的情况,我们只需要在变量符号表中加入名字b,同时将其对应的zval指针指向$a指向的zval内存地址即可。其内存结构变化示意图如下

image.png

这时候没有做内存开辟,那么什么时候会做内存开辟呢?答案是出现不可调和的矛盾时会产生内存开辟。
我们观察“$a赋值X”这一语句,赋值可为普通赋值(=)和引用赋值(=&),X可为常量或变量。所有的内存开辟都是在X端完成,整理列表如下。

image.png

可以看到,新建内存只有如下三种情况:

  1. 名字a不存在,赋给一个常量,这时候没办法必须新建
  2. $b=&$c,$a=$b,最开始$b和$c捆绑在一起,除非$b重新绑定到其他引用关系上,$b、$c的绑定关系是不会解除的,这时候$a想和$b在一起又不想和$c绑定(如果$a=&$b,那就是a、b、c绑定了),那就只有分出去一个$b的复制品给$a了,希望这样解释比较好理解。在程序中判断条件为赋值行为为=且X的is_ref=1。
  3. $b=$c,$a=&$b,这时候$b想和$a绑定在一起,$a又不想$c搀和进来(如果$b=&$c,那就是a、b、c绑定了),那就只有为难$b分出个复制品给$c了。在程序中判断条件为赋值行为为=&且X的refcount>1。
    可以看到所有要新建内存的地方都是矛盾不可调和的地方,这也是动态类型语言设计的高明之处,也是所谓的"Copy on write"原则的意思。

2.指针的问题("Change on write")
在之前我们谈到的$a,$b指向同一内存结构,实际上就是$a,$b名字对应的指针指向统一内存结构,对于如下语句

<?php  
$a = 1;  
$b = $a;  
echo '$a='.$a."\t".'$b='.$b."\n";  
$b = 2;  
echo '$a='.$a."\t".'$b='.$b."\n";  
  
$c = 1;  
$d = &$c;  
echo '$c='.$c."\t".'$d='.$d."\n";  
$d = 2;  
echo '$c='.$c."\t".'$d='.$d."\n";  
?>  

$a=1 $b=1
$a=1 $b=2
$c=1 $d=1
$c=2 $d=2

这里我们用一张图来说明其内存结构和指针指向变化示意图如下


image.png

这两个例子的唯一不同在于定义$d时加上了一个引用定义符&。
为什么$b赋值时指向发生了变化而$d赋值时没有变化,是么时候指针指向才会发生变化呢?答案是同样是出现不可调和的矛盾时会产生指针指向改变。
同样我们观察“$a赋值X”这一语句,赋值可为普通赋值(=)和引用赋值(=&),X可为常量或变量。所有的指针指向改变都是在$a端完成。
这里我就不再列表了,可以同样按照以上方法分析,结论同样是三种情况下指针指向发生改变:

  1. 名字a不存在,这时候新建了名字没办法必须将指针指向一个地方
  2. $b=1,$a=$b,$a=2,最开始$a和$b指向同一内存结构,当$a要指向一个新的值又不希望$c指向这个值,那么只有将$a指针从原来的指向$b内存结构改为指向新建的内存结构。在程序中判断条件为赋值行为为=且$a的refcount>1。
  3. $b=1,$c=2,$a=&$b,$a=&$c,这时候$a想和$c绑定在一起,只能绑定一个内存结构,$a只有舍弃$b,将$a的指针从原来指向$b内存结构改为指向$c内存结构。在程序中判断条件为赋值行为为=&且$a的is_ref=1。
    可以看到所有要改变指针指向的地方同样是矛盾不可调和的地方,这同样也是动态类型语言设计的高明之处,也是所谓的"Change on write"原则的意思。

实际上所有弱类型的语言机理大概都是如此,只有按照这样的逻辑来设计的动态语言才是最优性能同时不反人类的,下一节深入到PHP的存储结构来讲解PHP的引用,说明PHP引用特别是对象引用容易被错误理解的地方。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,387评论 3 44
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 1,673评论 0 4
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 1,982评论 0 12
  • iOS面试小贴士 ———————————————回答好下面的足够了------------------------...
    不言不爱阅读 1,876评论 0 7
  • 开篇 本文章阅读用时15分钟,属于C#零基础入门的教程。 建议按照文章项目进行实战,多写代码,多联系。 这是小白学...
    做全栈攻城狮阅读 1,695评论 0 6