构造函数中的引用
时间:2008-08-22 来源:shell-wgy
构造函数中的引用
最今学习PHP的类,对其中类的引用做一个小小结
以下代码来自PHP手册
class Foo {
function Foo($name) {
// 在全局数组 $globalref 中建立一个引用
global $globalref;
$globalref[] = &$this;
// 将名字设定为传递的值
$this->setName($name);
// 并输出之
$this->echoName();
}
function echoName() {
echo "
",$this->name;
}
function setName($name) {
$this->name = $name;
}
}
?>
下面来检查一下用拷贝运算符 = 创建的 $bar1 和用引用运算符 =& 创建的 $bar2 有没有区别...
= new Foo('set in constructor');
$bar1->echoName();
$globalref[0]->echoName();
/* 输出:
set in constructor
set in constructor
set in constructor */
$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();
/* 输出:
set in constructor
set in constructor
set in constructor */
?>
显然没有区别,但实际上有一个非常重要的区别:$bar1 和 $globalref[0] 并没有被引用,它们不是同一个变量。这是因为"new"默认并不返回引用,而返回一个拷贝.
当用 new 运算符,实际上已经生成一个实例,此时执行$bar1 = new Foo('xxx'),在内存中只是对类Foo的一个简单拷贝.$globalref[0]指向当前原来的实例,这样,当后面修改bar1时,$global[0]实际上不会随之改变. 当执行$bar2 = & new Foo('xxx')时,$bar2就成了指向实例的引用,这和$global[1]就成了指向同一个实例的引用了.
为了能更详细地说明引用,看下图
把$bar1对Foo的拷贝看作f1,把bar2对Foo的拷贝看作f2,其实f1,f2在内存中的信息是完全相同的,毕竟来自同一个Foo.所以上图的Class作为共用示图.
$bar1根据f1中的信息进行处理,由于代码中$globalref[]是在$bar1调用具体方法之前申明的全局变量.$globalref[0]没有被引用,所以$globalref[0]指向当前原来的实例.
而$bar2是对Foo的引用,$bar2和$globalref[1]指向同一个实例
注:在返回拷贝而不是引用中并没有性能上的损失(因为 PHP 4 及以上版本使用了引用计数)。相反更多情况下工作于拷贝而不是引用上更好,因为建立引用需要一些时间而建立拷贝实际上不花时间(除非它们都不是大的数组或对象,而其中之一跟着另一个变,那使用引用来同时修改它们会更聪明一些)。
为了证明上面所述,看下面例子
// 现在改个名字,你预期什么结果?
// 你可能预期 $bar1 和 $globalref[0] 二者的名字都改了...
$bar1->setName('set from outside');
// 但如同前面说的,并不是这样。
$bar1->echoName();
$globalref[0]->echoName();
/* 输出为:
set from outside
set in constructor */
// 现在看看 $bar2 和 $globalref[1] 有没有区别
$bar2->setName('set from outside');
// 幸运的是它们不但相同,根本就是同一个变量。
// 因此 $bar2->name 和 $globalref[1]->name 也是同一个变量。
$bar2->echoName();
$globalref[1]->echoName();
/* 输出为:
set from outside
set from outside */
最今学习PHP的类,对其中类的引用做一个小小结
以下代码来自PHP手册
class Foo {
function Foo($name) {
// 在全局数组 $globalref 中建立一个引用
global $globalref;
$globalref[] = &$this;
// 将名字设定为传递的值
$this->setName($name);
// 并输出之
$this->echoName();
}
function echoName() {
echo "
",$this->name;
}
function setName($name) {
$this->name = $name;
}
}
?>
下面来检查一下用拷贝运算符 = 创建的 $bar1 和用引用运算符 =& 创建的 $bar2 有没有区别...
= new Foo('set in constructor');
$bar1->echoName();
$globalref[0]->echoName();
/* 输出:
set in constructor
set in constructor
set in constructor */
$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();
/* 输出:
set in constructor
set in constructor
set in constructor */
?>
显然没有区别,但实际上有一个非常重要的区别:$bar1 和 $globalref[0] 并没有被引用,它们不是同一个变量。这是因为"new"默认并不返回引用,而返回一个拷贝.
当用 new 运算符,实际上已经生成一个实例,此时执行$bar1 = new Foo('xxx'),在内存中只是对类Foo的一个简单拷贝.$globalref[0]指向当前原来的实例,这样,当后面修改bar1时,$global[0]实际上不会随之改变. 当执行$bar2 = & new Foo('xxx')时,$bar2就成了指向实例的引用,这和$global[1]就成了指向同一个实例的引用了.
为了能更详细地说明引用,看下图
把$bar1对Foo的拷贝看作f1,把bar2对Foo的拷贝看作f2,其实f1,f2在内存中的信息是完全相同的,毕竟来自同一个Foo.所以上图的Class作为共用示图.
$bar1根据f1中的信息进行处理,由于代码中$globalref[]是在$bar1调用具体方法之前申明的全局变量.$globalref[0]没有被引用,所以$globalref[0]指向当前原来的实例.
而$bar2是对Foo的引用,$bar2和$globalref[1]指向同一个实例
注:在返回拷贝而不是引用中并没有性能上的损失(因为 PHP 4 及以上版本使用了引用计数)。相反更多情况下工作于拷贝而不是引用上更好,因为建立引用需要一些时间而建立拷贝实际上不花时间(除非它们都不是大的数组或对象,而其中之一跟着另一个变,那使用引用来同时修改它们会更聪明一些)。
为了证明上面所述,看下面例子
// 现在改个名字,你预期什么结果?
// 你可能预期 $bar1 和 $globalref[0] 二者的名字都改了...
$bar1->setName('set from outside');
// 但如同前面说的,并不是这样。
$bar1->echoName();
$globalref[0]->echoName();
/* 输出为:
set from outside
set in constructor */
// 现在看看 $bar2 和 $globalref[1] 有没有区别
$bar2->setName('set from outside');
// 幸运的是它们不但相同,根本就是同一个变量。
// 因此 $bar2->name 和 $globalref[1]->name 也是同一个变量。
$bar2->echoName();
$globalref[1]->echoName();
/* 输出为:
set from outside
set from outside */
相关阅读 更多 +