给力星

Web Developer

重温PHP手册 – 引用

引用

在 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)

注意,如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。

$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'\n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable'

把 global $var; 当成是 $var =& $GLOBALS[‘var’]; 的简写。从而将其它引用赋给 $var 只改变了本地变量的引用。

Note

引用总是指向变量的内容:

$a = 1;
$c = 2;
$b =& $a;   // $b points to 1
$a =& $c;   // $a points now to 2, but $b still to 1;
echo $a, " ", $b;   // Output: 2 1

引用不是什么

引用不是指针,所以下面的结构不会产生预期的效果:

function foo(&$var)
{
    $var =& $GLOBALS["baz"];
}
foo($bar);

不能通过引用机制将 $bar 在函数调用范围内绑定到别的变量上面,与上面声明为 global 的变量赋于一个引用,该引用只在函数局部范围内可见类似。可以使用引用返回来引用被函数选择的变量。

引用传递

可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值。注意在函数调用时没有引用符号——只有函数定义中有

function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);

以下内容可以通过引用传递:

  • 变量,例如 foo($a)
  • New 语句,例如 foo(new foobar())
  • 从函数中返回的引用,例如:
function &bar()
{
    $a = 5;
    return $a;
}
foo(bar());

Note

引用参数不能设置默认值,但可以设置为NULL值

// 这样是错的
function use_reference( $someParam, &$param =& $POST ) {}

// 但这样可以
function use_reference( $someParam, &$param = null ) {}

引用返回

引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!

class foo {
    public $value = 42;

    public function &getValue() {
        return $this->value;
    }
}

$obj = new foo;
$myValue = &$obj->getValue(); // reference to $obj->value, which is 42.
$obj->value = 2;
echo $myValue;                // prints the new value of $obj->value, 2.

和参数传递不同,引用返回必须在两个地方都用 & 符号——指出返回的是一个引用,而不是通常的一个拷贝,同样也指出 $myValue 是作为引用的绑定,而不是通常的赋值。

Note

引用返回时,= 和 =& 的区别:如果使用 = ,则返回的是值而不是引用

function &func(){
    static $static = 0;
    $static++;
    return $static;
}

$var1 =& func();
echo "var1:", $var1; // 1
func();
func();
echo "var1:", $var1; // 3

$var2 = func(); // assignment without the &
echo "var2:", $var2; // 4
func();
func();
echo "var1:", $var1; // 6
echo "var2:", $var2; // still 4

在 PHP5 中,返回新对象时,默认是返回引用,因此可以达到链式操作的效果:

class Foo {
    public function sayHi() {
        echo 'Hi, ';
        return $this;
    }
    public function sayHello() {
        echo 'Hello';
        return $this;
    }

}

function test() {
    return new Foo();
}

test()->sayHi()->sayHello();

取消引用

当 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。

$a = 1;
$b =& $a;
unset($a);
echo $b;    // 1

上述例子可通过下面的演示,来弄清楚引用的工作机制:

/* Imagine this is memory map
___________________________________
|pointer  | value  | variable      |
-----------------------------------
|   1     |  NULL  |         ---   |
|   2     |  NULL  |         ---   |
|   3     |  NULL  |         ---   |
----------------------------------- */

// Create some variables
$a = 10;
$b = 20;
$c = 30;

/* Look at memory
___________________________________
|pointer  | value  | variable      |
-----------------------------------
|   1     |  10    |     $a        |
|   2     |  20    |     $b        |
|   3     |  30    |     $c        |
----------------------------------- */

$a =& $b;

/* Look at memory
// value of $a is destroyed and pointer is free
___________________________________
|pointer  | value  | variable      |
-----------------------------------
|   1     |  NULL  |     --        |
|   2     |  20    |     $b, $a    |
|   3     |  30    |     $c        |
----------------------------------- */

unset($a);

/* Look at memory
// $a is destroyed, but the value still in memory.
___________________________________
|pointer  | value  | variable      |
-----------------------------------
|   1     |  NULL  |     --        |
|   2     |  20    |     $b        |
|   3     |  30    |     $c        |
----------------------------------- */

引用定位

许多 PHP 的语法结构是通过引用机制实现的,所以上述有关引用绑定的一切也都适用于这些结构。

global 引用

当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用。也就是说下面两者是相同的:

// 两种定义是等价的
global $var;
$val =& GLOBALS['var'];

这意味着,例如,unset($var) 不会 unset 全局变量。

$this

在一个对象的方法中,$this 永远是调用它的对象的引用。

发表评论

电子邮件地址不会被公开。