发布网友 发布时间:2022-04-10 10:46
共4个回答
懂视网 时间:2022-04-10 15:07
Note:
如果具有引用的数组被拷贝,其值不会解除引用。对于数组传值给函数也是如此。
Note:
如果对一个未定义的变量进行引用赋值、引用参数传递或引用返回,则会自动创建该变量。
Example #1 对未定义的变量使用引用
<?php
function foo(&$var) { }
foo($a); // $a is "created" and assigned to null
$b = array();
foo($b[‘b‘]);
var_dump(array_key_exists(‘b‘, $b)); // bool(true)
$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, ‘d‘)); // bool(true)
?>
同样的语法可以用在函数中,它返回引用,以及用在 new 运算符中(PHP 4.0.4 以及以后版本):
<?php
$bar =& new fooclass();
$foo =& find_var($bar);
?>
自 PHP 5 起,new 自动返回引用,因此在此使用 =& 已经过时了并且会产生 E_STRICT 级别的消息。
Note:
不用 & 运算符导致对象生成了一个拷贝。如果在类中用 $this,它将作用于该类当前的实例。没有用 & 的赋值将拷贝这个实例(例如对象)并且 $this将作用于这个拷贝上,这并不总是想要的结果。由于性能和内存消耗的问题,通常只想工作在一个实例上面。
尽管可以用 @ 运算符来抑制构造函数中的任何错误信息,例如用 @new,但用 &new 语句时这不起效果。这是 Zend 引擎的一个限制并且会导致一个解析错误。
Warning如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。
Example #2 在函数内引用全局变量
<?php
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // visible only inside the function
} else {
$GLOBALS["var2"] =& $var1; // visible also in global context
}
}
global_references(false);
echo "var2 is set to ‘$var2‘
"; // var2 is set to ‘‘
global_references(true);
echo "var2 is set to ‘$var2‘
"; // var2 is set to ‘Example variable‘
?>
把 global $var; 当成是 $var =& $GLOBALS[‘var‘]; 的简写。从而将其它引用赋给 $var 只改变了本地变量的引用。
Note:
如果在 foreach 语句中给一个具有引用的变量赋值,被引用的对象也被改变。
Example #3 引用与 foreach 语句
<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
// do something
}
echo $ref; // 3 - last element of the iterated array
?>
引用做的第二件事是用引用传递变量。这是通过在函数内建立一个本地变量并且该变量在呼叫范围内引用了同一个内容来实现的。例如:
<?php
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
?>
将使 $a 变成 6。这是因为在 foo 函数中变量 $var 指向了和 $a 指向的同一个内容。更多详细解释见引用传递。
引用做的第三件事是引用返回。
数组引用的一个bug(后来仔细推敲,其实不是bug)
摘自:http://www.php.net/manual/zh/language.references.whatdo.php
It appears that references can have side-effects. Below are two examples. Both are simply copying one array to another. In the second example, a reference is made to a value in the first array before the copy. In the first example the value at index 0 points to two separate memory locations. In the second example, the value at index 0 points to the same memory location.
I won‘t say this is a bug, because I don‘t know what the designed behavior of PHP is, but I don‘t think ANY developers would expect this behavior, so look out.
An example of where this could cause problems is if you do an array copy in a script and expect on type of behavior, but then later add a reference to a value in the array earlier in the script, and then find that the array copy behavior has unexpectedly changed.
<?php输出:
before:// Example two
$arr3=array(1);
$a=&$arr3[0];
echo"
before:
";
echo"$a == $a
";
echo"$arr3[0] == {$arr3[0]}
";
$arr4=$arr3;
$arr4[0]++;
echo"
after:
";
echo"$a == $a
";
echo"$arr3[0] == {$arr3[0]}
";
echo"$arr4[0] == {$arr4[0]}
";
输出:
before:?>
分析说明:对于“Example two”,刚开始还以为是个bug,其实仔细推敲,非也,分析如下,
在赋值(拷贝)
$arr4=$arr3;之前,还有个对$arr3的第一个元素建立引用的过程,即
$a=&$arr3[0];所以在后来的赋值拷贝( $arr4=$arr3; ),会把这个引用一并拷贝过去,所以说
$a、$arr3[0]、$arr4[0] 三者其实是引用关系,指向同一个地方。
mysql引用并不是指针
标签:any link 处理 back rate 原因 工作 外部 对象
热心网友 时间:2022-04-10 12:15
不是,但是引用的本质和指针一样都是传递地址,区别是编译器会安排函数在使用时候采用不同的内存机制和寻址方式。
举例
void func(int & r,int *p)先看输出结果
引用传递后,外部变量实参a转为形参r,b转为p,其中r作为引用,在函数内不分配内存直接使用传递进来的地址,并当做原变量本身使用,因此我们说r是a的别名,即直接寻址;而p为指针,在进入函数后在栈上必须分配内存空间,用来保存传递进来的地址,之后以指针方式间接寻址以操作数据。
要进一步了解必须进入编程的量子世界去理解,下面是反汇编后的编译器编译的汇编代码,让我们看看其本质吧。
调用
lea eax,[b]-将变量b的地址值存入寄存器eax
push eax-寄存器eax入栈
同理,将变量a的地址入栈,随后调用func,0CE11D8H为func函数的跳转指令所在地址。
可见,由于a是以引用形式传递,所以取的是a的地址而不是a的值,而b是显式取地址,所以取的也是b的地址,可以看出在调用函数前,指针和引用都是将地址压栈,因此从调用角度看,引用的区别是隐含取地址,而指针的是显式取地址。
函数内
函数开头一段指令是每个函数都有的,其作用就是保存执行函数体之前的所有CPU寄存器状态到栈内,包括基地址、栈指针等,以便完成函数之后弹栈获得原先状态继续执行后续指令。此时传递的a和b的地址被压在这部分数据下面,这个要记住,因为最后函数结束时会执行ret指令弹栈,是否需要返回看需要,这些工作编译器会安排好。
r++部分(引用)
0026294E mov eax,dword ptr [r]
此处的r实际为a的地址存在栈内的地址值(不是传入的a的地址),作为双字指针取出其所指地址中的值,存入寄存器eax,这个值才是a的地址。
00262951 mov ecx,dword ptr [eax]
将寄存器eax的值再次以指针方式取出其指向的地址中的值,也就是eax内存储的是a的地址,作为指针取出其值就是a的值,也就是1,存入寄存器ecx。
00262953 add ecx,1
这个不用讲了吧,exc+1,就是执行r++,就是a++的关键操作。
00262956 mov edx,dword ptr [r]
再次取a的地址存入edx寄存器
00262959 mov dword ptr [edx],ecx
将ecx的运算结果写入a的地址中。
(*p)++(指针)
指令几乎一模一样,可以看出,在函数内,r++和(*p)++是等价的,这意味着,r和p不同。r是实参a的别名,可以将r看做a本身来看待,或者说r代表了a的地址,好比a穿越时空来到函数内部可以被直接访问到,只是换了个名字而已,而如果(*p)等价于引用,则意味着p保存着b的地址。所以从源代码角度看,p是个局部指针变量保存传入的地址值,而r就是实参a本身。
热心网友 时间:2022-04-10 13:33
是用匿名的常量指针来实现的热心网友 时间:2022-04-10 15:08
不是, 引用和指针还是有很大差别的