Chinaunix首页 | 论坛 | 博客
  • 博客访问: 84990
  • 博文数量: 20
  • 博客积分: 1490
  • 博客等级: 上尉
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-18 08:43
文章分类

全部博文(20)

文章存档

2013年(1)

2010年(1)

2009年(4)

2008年(14)

我的朋友
最近访客

分类:

2008-08-22 10:02:05

最今学习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 有没有区别...

$bar1 = 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 */


 

 

阅读(696) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~