文字

引用传递

可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值。语法如下:

<?php
function  foo (& $var )
{
    
$var ++;
}

$a = 5 ;
foo ( $a );
// $a is 6 here
?>
注意在函数调用时没有引用符号——只有函数定义中有。光是函数定义就足够使参数通过引用来正确传递了。在最近版本的 PHP 中如果把 & 用在 foo(&$a); 中会得到一条警告说“Call-time pass-by-reference”已经过时了。

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

  • 变量,例如 foo($a)
  • New 语句,例如 foo(new foobar())
  • 从函数中返回的引用,例如:

    <?php
    function & bar ()
    {
        
    $a  5 ;
        return 
    $a ;
    }
    foo ( bar ());
    ?>
    详细解释见引用返回。

任何其它表达式都不能通过引用传递,结果未定义。例如下面引用传递的例子是无效的:

<?php
function  foo (& $var )
{
    
$var ++;
}
function 
bar ()  // Note the missing &
{
    
$a  5 ;
    return 
$a ;
}
foo ( bar ());  // 自 PHP 5.0.5 起导致致命错误,自 PHP 5.1.1 起导致严格模式错误
            // 自 PHP 7.0 起导致 notice 信息
foo ( $a  5 // 表达式,不是变量
foo ( 5 // 导致致命错误
?>
这些条件是 PHP 4.0.4 以及以后版本有的。

用户评论:

[#1] mike at eastghost dot com [2015-05-19 19:06:22]

beware unset()  destroys references

$x = 'x';
change( $x );
echo $x; // outputs "x" not "q23"  ---- remove the unset() and output is "q23" not "x"

function change( & $x )
{
    unset( $x );
    $x = 'q23';
    return true;
}

[#2] no at spam dot please [2015-05-05 08:36:52]

agreed : this change produces less readable code.

additionally, it breaks many existing perfectly working codes which are not portable anymore and in some cases will require complex modifications

another issue regards the fatal error that is produced : how the hell am i supposed to do if i want to allow the user to use a value that is not even in a variable, or the return or a function call, or use call_user_func... this produces many occasions for a code to even break at run time

[#3] tnestved at yahoo dot com [2014-10-14 13:54:09]

By removing the ability to include the reference sign on function calls where pass-by-reference is incurred (I.e., function definition uses &), the readability of the code suffers, as one has to look at the function definition to know if the variable being passed is by-ref or not (I.e., potential to be modified).  If both function calls and function definitions require the reference sign (I.e., &), readability is improved, and it also lessens the potential of an inadvertent error in the code itself.  Going full on fatal error in 5.4.0 now forces everyone to have less readable code.  That is, does a function merely use the variable, or potentially modify it...now we have to find the function definition and physically look at it to know, whereas before we would know the intent immediately.

[#4] phpnet at holodyn dot com [2014-03-26 18:38:10]

The notes indicate that a function variable reference will receive a deprecated warning in the 5.3 series, however when calling the function via call_user_func the operation aborts without fatal error.

This is not a "bug" since it is not likely worth resolving, however should be noted in this documentation.

[#5] diabolos @t gmail dot com [2012-07-27 14:46:36]

<?php



// ------------------------------------------
// Demo call of the swap(...) function below.

 
$a 123.456;
 
$b 'abcDEF';
  
 print 
"<pre>Define:\na = $a\nb = '$b'</pre>";
 
swap($a,$b);
 print 
"<pre>After swap(a,b):\na = '$a'\nb = $b</pre>";

// -------------------------------

   
function swap (&$arg1, &$arg2)
{

// Swap contents of indicated variables.
   
$w=$arg1;   $arg1=$arg2;   $arg2=$w;
}

?>

[#6] fdelizy at unfreeze dot net [2006-08-12 09:32:43]

Some have noticed that reference parameters can not be assigned a default value. It's actually wrong, they can be assigned a value as the other variables, but can't have a "default reference value", for instance this code won't compile :

<?php
function use_reference$someParam, &$param =& $POST )
{
 ...

?>


But this one will work :

<?php
function use_reference$someParam, &$param null )
?>


So here is a workaround to have a default value for reference parameters :

<?php
$array1 
= array ( 'test''test2' );

function 
AddTo$key$val, &$array null)
{
    if ( 
$array == null )
    {
      
$array =& $_POST;
    }

    
$array$key ] = $val ;
}

AddTo"indirect test""test"$array1 );
AddTo"indirect POST test""test" );

echo 
"Array 1 " ;
print_r $array1);

echo 
"_POST ";
print_r$_POST );

?>


And this scripts output is :

Array 1 Array
(
    [0] => test
    [1] => test2
    [indirect test] => test
)
_POST Array
(
    [indirect POST test] => test
)

Of course that means you can only assign default reference to globals or super globals variables. 

Have fun

[#7] pillepop2003 at yahoo dot de [2005-02-13 08:08:44]

PHP has a strange behavior when passing a part of an array by reference, that does not yet exist.

<?php
    
function func(&$a)
    {
        
// void();
    
}
    
    
$a['one'] =1;
    
func($a['two']);
?>


var_dump($a) returns

array(2) {
["one"]=>
int(1)
["two"]=>
NULL
}

...which seems to be not intentional!

[#8] obscvresovl at NOSPAM dot hotmail dot com [2004-12-25 22:51:10]

Just a simple note...

<?php

$num 
1;

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

blah($num);

echo 
$num#2

?>


<?php

$num 
1;

function 
blah()
{
    
$var =& $GLOBALS["num"];
    
$var++;
}

blah();

echo 
$num#2

?>


Both codes do the same thing! The second code "explains" how passage of parameters by reference works.

[#9] Sergio Santana: ssantana at tlaloc dot imta dot mx [2004-09-10 08:25:16]

Sometimes we need functions for building or modifying arrays whose elements are to be references to other variables (arrays or objects for instance). In this example, I wrote two functions 'tst' and 'tst1' that perform this task. Note how the functions are written, and how they are used.

<?php
function tst(&$arr$r) {
  
// The argument '$arr' is declared to be passed by reference, 
  // but '$r' is not;
  // however, in the function's body, we use a reference to 
  // the '$r' argument
  
  
array_push($arr, &$r); 
  
// Alternatively, this also could be $arr[] = &$r (in this case)
}
  
$arr0 = array();          // an empty array
$arr1 = array(1,2,3);   // the array to be referenced in $arr0

// Note how we call the function:
tst($arr0, &$arr1); // We are passing a reference to '$arr1' in the call !

print_r($arr0); // Contains just the reference to $arr1

array_push($arr05); // we add another element to $arr0
array_push($arr118); // we add another element to $arr1 as well

print_r($arr1);  
print_r($arr0); // Changes in $arr1 are reflected in $arr0

// -----------------------------------------
// A simpler way to do this:

function tst1(&$arr, &$r) {
  
// Both arguments '$arr' and '$r" are declared to be passed by
  // reference, 
  // again, in the function's body, we use a reference to 
  // the '$r' argument
  
  
array_push($arr, &$r); 
  
// Alternatively, this also could be $arr[] = &$r (in this case)
}

  
$arr0 = array();          // an empty array
$arr1 = array(1,2,3);   // the array to be referenced in $arr0

// Note how we call the function:
tst1($arr0$arr1); // 'tst1' understands '$r' is a reference to '$arr1'

echo "-------- 2nd. alternative ------------ <br>\n";

print_r($arr0); // Contains just the reference to $arr1

array_push($arr05); // we add another element to $arr0
array_push($arr118);

print_r($arr1);  
print_r($arr0); // Changes in $arr1 are reflected in $arr0

// This outputs:
// X-Powered-By: PHP/4.1.2
// Content-type: text/html
// 
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//         )
// 
// )
// Array
// (
//     [0] => 1
//     [1] => 2
//     [2] => 3
//     [3] => 18
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//             [3] => 18
//         )
// 
//     [1] => 5
// )
// -------- 2nd. alternative ------------ 
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//         )
// 
// )
// Array
// (
//     [0] => 1
//     [1] => 2
//     [2] => 3
//     [3] => 18
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//             [3] => 18
//         )
// 
//     [1] => 5
// )
?>


In both cases we get the same result.

I hope this is somehow useful

Sergio.

上一篇: 下一篇: