php变量的引用,如果使用的恰当,会带来效率的提升,相反,效率下降

$array = range(, );
$ref =& $array;
var_dump(count($array)); //

count是个内置函数,参数只接收传值,但现在传入的参数$array是个引用,由于在php5中,某个值是不能引用变量和非引用变量之间使用

针对这个例子来说,即在count内部,php引擎会copy一个$arrray指向的zval,所以效率就降下来了

如果传的count的参数不是引用,那么count内部不会做copy动作, 在copy内部,接收的参数其实也会指向 $array指向的zval,因为php数组的名称就代表了在内存的地址

$a="123";

$b=$a; // $a,$b 指向同一个zval_1, type=IS_STRING, refcount_gc=2, is_ref_gc=0

$c=&$b; //由于同一值(zval)不能被引用变量和非引用变量之间使用,要分离  , $c, $d指向zval_2 type=IS_STRING, refcount_gc=2, is_ref_gc=1

$d=$c //如上也要分离,尽管$d的值没有重新赋值 $d 指向zval_3,type=IS_STRING, ref_count_gc=1,is_ref_gc=0

在php7中,某个值是可能在引用变量和非引用变量之间使用的,只有当发生变化时,才会copy一份zval

$c=&$b; 因为有$c,$d两个变量 zval.value.ref->gc.refcount=2  zval.value.ref->val.value.str.gc.refcount=2 ($a,$b)

$d=$c   zval.value.ref->val.value.str.gc.refcount=3 ($a,$b ,$d)

struct _zval_struct {
zend_value value; /* value */
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar type, /* active type */
zend_uchar type_flags,
zend_uchar const_flags,
zend_uchar reserved) /* call info for EX(This) */
} v;
uint32_t type_info;
} u1;
union {
uint32_t var_flags;
uint32_t next; /* hash collision chain */
uint32_t cache_slot; /* literal cache slot */
uint32_t lineno; /* line number (for ast nodes) */
uint32_t num_args; /* arguments number for EX(This) */
uint32_t fe_pos; /* foreach position */
uint32_t fe_iter_idx; /* foreach iterator index */
} u2;
}; typedef union _zend_value {
zend_long lval; /* long value */
double dval; /* double value */
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zend_ast_ref *ast;
zval *zv;
void *ptr;
zend_class_entry *ce;
zend_function *func;
struct {
uint32_t w1;
uint32_t w2;
} ww;
} zend_value;
struct _zend_refcounted {
zend_refcounted_h gc;
}; typedef struct _zend_refcounted_h {
uint32_t refcount; /* reference counter 32-bit */
union {
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type,
zend_uchar flags, /* used for strings & objects */
uint16_t gc_info) /* keeps GC root number (or 0) and color */
} v;
uint32_t type_info;
} u;
} zend_refcounted_h;

所以说php当初被发明出来,是为了更方便使用者, 这样的结果就是使用方可以随意写代码,但php引擎就要做大量的维护工作

那么php的参数是如何运行的?

function test(&$b){
$b=;
} $a=;
test($a);

$a的值为2

如果说

 function test($b){

  $b=;

}

$a=;

test($a);

$a的结果是1

因为我们形参是实参的一个拷贝,对拷贝的操作不会影响到实参

$a=1;

首先分配一个zval*的内存,填充zval中的value(zva.value.lval=1)以及type(zva.type=IS_LONG)

然后放到active_symbol_table这个hashTable中, key为'a' value为一个zval指针,该指针指向上面的zval

$a="abc"

通过zend_hash_quick_get(EG(active_symbol_table),'a', ptr) 得到key为'a' 的对应的value的内存地址,即上面zval的地址,再设置其zval.value.str.val="abc";

$a=2;

通过zend_hash_quick_get(EG(active_symbol_table),'a', ptr) 得到key为'a' 的对应的value的内存地址,即上面zval的地址,

因为此时zval的类型为IS_STRING,故要释放到zva.value.str这段内存

再设置其zval.value.lval=2;

$b=$a;

首先zend_hash_quick_get(EG(active_symbol_table),'a')得到变量a 对应的zval的地址

然后zend_hash_quick_set(EG(active_symbol_table),'b', 上面zval对应的地址);

$c=&$b

分离zval, 再次分配一个zval类型的内存,copy value和type,初始为refcount_gc以及is_ref_gc

zend_hash_quick_set(EG(active_symbol_table),'b', 新的zval对应的地址);

zend_hash_quick_set(EG(active_symbol_table),'c', 新的zval对应的地址);

$c=5;

zend_hash_quick_get(EG(active_symbol_table),'c')得到变量c 对应的zval的地址

zval.value.lval=5

php引用使用不恰当而产生问题的地方的更多相关文章

  1. iOS循环引用问题

    今天面试问道了循环引用,所以就看了看,原来只是知道使用了Block容易造成循环引用.今天就来简单的介绍一些循环引用. 先来简单介绍一下什么是循环引用? 循环引用可以简单的理解成:A对象引用了B对象,B ...

  2. 谈谈 C++ 中的右值引用

    转自:https://liam0205.me/2016/12/11/rvalue-reference-in-Cpp/ 最近在改 XGBoost 的代码.XGBoost 在代码中使用了很多来自 C++1 ...

  3. 深入PHP中的引用

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 简单变量引用 对象引用 函数参数传递 函数返回引用   虽然常说做C/C++编程的程序员转做PHP编程很快可以上手,但是对于 ...

  4. (C/C++学习)21.C++中返回引用和返回对象以及传引用和传对象问题

    说明:在学习和编写C++代码时,经常会遇到这样的问题:一个带返回值的函数,到底应该返回值呢,还是应该返回引用呢:在传递参数的时候,是应该传递参数的引用呢,还是应该传值呢?请看下面代码: void my ...

  5. 具体解释C++引用——带你走进引用的世界

     一.介绍引用 首先说引用是什么,大家能够记住,引用就是一个别名,比方小王有个绰号叫小狗.他的妈妈喊小狗回家吃饭.那就是在喊小王回家吃饭. 接下来我们用两行代码来声明一个引用(就拿小王和小狗来说吧 ...

  6. python列表与字符串、元组的区别以及列表引用的方式

    一.字符串 字符串也可以用下标取值.切片.for循环.len()取长度以及 in 和 not in 来进行操作. 但字符串是不可变的,不能被更改.只能构造一个“新的”字符串来存取你想要修改后的数据. ...

  7. Android如何正确引用其它jar包 (转)

    转:http://blog.csdn.net/liranke/article/details/17226083 Android项目常常需要引用自定义的或者外部的jar包,这里提供一些经验,供参考. 一 ...

  8. iOS项目转移到自动引用计数

    这里主要参考了Apple官方文档:Transitioning to ARC Release Notes 在支持iOS5的Xcode4中,创建项目会看到这样的选项: 这是iOS5的新特性,自动对象引用计 ...

  9. WinForm引用ActiveX组件,对Com组件的学习

    1.WinForm引用Adobe PDF Reader 工作中写WinForm程序经常会引用第三方的组件,包括引用Com组件,做了一个桌面程序需要展示PDF,看了些其它的开源组件对PDF的兼容性都不是 ...

随机推荐

  1. Centos记录所有用户登录和操作的详细日志

    1.起因 最近Linux服务器上一些文件呗篡改,想追查已经查不到记录了,所以得想个办法记录下所有用户的操作记录. 一般大家通常会采用history来记录,但是history有个缺陷就是默认是1000行 ...

  2. 2018.10.16 NOIP模拟 长者(主席树+hash)

    传送门 考试的时候开始sb的以为需要可持久化trietrietrie树,发现建树时空都是O(n2)O(n^2)O(n2)的. 然后发现由于每次只从原来的字符串改一个字符. 因此直接主席树维护区间has ...

  3. Google Map API申请

    https://code.google.com/apis/console 当然需要先有个Google账户登录. 然后需要建一个项目. 然后根据package+sha1码获取密钥key 然后就可以创建凭 ...

  4. springmvc 开涛 拦截器

    拦截器有三个方法:preHandle, postHandle, afterCompletion ***-servlet.xml <bean name="/test" clas ...

  5. chrome 概述

    Chrome, Firebug, Filddle 调试:http://www.zhihu.com/question/35667558/answer/63936233 Chrome开发者工具系列: ht ...

  6. [翻译] Using Custom Functions in a Report 在报表中使用自己义函数

    Using Custom Functions in a Report  在报表中使用自己义函数   FastReport has a large number of built-in standard ...

  7. c# 协变和逆变的理解

    1. 是什么 1.1 协变 协变指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型.如 string 到 object 的转换.多见于类型参数用作方法的返回值. 1.2 逆变 逆变指能够 ...

  8. 微信公众平台如何与Web App结合?

    Web App简而言之就是为移动平台而优化的网页,它可以表现得和原生应用一样,并且克服了原生应用一些固有的缺点.一般而言Web App最大的入口是浏览器,但现在微信公众平台作为新兴的平台,结合其内置浏 ...

  9. Replication--查看未分发命令和预估所需时间

    当复制有延迟时,我们可以使用复制监视器来查看各订阅的未分发命令书和预估所需时间,如下图: 但是当分发和订阅数比较多的时候,依次查看比较费时,我们可以使用sys.sp_replmonitorsubscr ...

  10. DBCC--CHECKDB--结果收集

    --由宋沄剑提供 CREATE TABLE [dbo].[dbcc_history]( [Error] [int] NULL, [Level] [int] NULL, [State] [int] NU ...