Thoughts raised by PHP's call_user_func pass through reference

  • 2020-03-31 20:55:27
  • OfStack

Problem presentation
Bercmisir left a message in the hospital. Regarding the documentation of the call_user_func function in the PHP manual, it is roughly as follows:
http://php.net/manual/en/function.call-user-func.php

There is a sentence under parameter:
Note: Note that the parameters for call_user_func() are not passed by reference.

The argument to this function cannot be passed by reference.

Here's another example:
 
error_reporting(E_ALL); 
function increment(&$var) 
{ 
$var++; 
} 
$a = 0; 
call_user_func('increment', $a); 
echo $a."n"; 
call_user_func_array('increment', array(&$a)); // You can use this instead before PHP 5.3 
echo $a."n"; 
?> 

The output is:
0
1

Bercmisir's problem:
Call_user_func (' increment, $a); The output is 0, and call_user_func('increment', &$a); The output is 1, which says you can't rely on a reference to pass.

Roots back
And then further roots, this Note information is http://bugs.php.net/bug.php? Id =24931 is the last result of the bug.
And in call_user_func('increment', &$a); Although the result of 1 is output, in general, there is a warning message: Deprecated: call-time pass-by-reference has been Deprecated.

What's the reason?
Here's an example:
 
error_reporting(E_ALL); 
function increment(&$var) 
{ 
$var++; 
} 
$x = 1; 
increment($x); 
echo $x; 
?> 

The result is 2, and there is no warning like expected to be a reference, value given. On the contrary, if you change line 8 to &$x, you will get a cancel warning. This proves that, in PHP, variables will decide whether to transmit a reference or a value based on whether the parameter needs a reference or a value, and it does not need to be explicitly passed (as opposed to explicitly passed, which is about to be abolished).

further
http://www.php.net/manual/en/language.references.pass.php
In the PHP manual, in the section on passing references, there is a Note in the middle that says that there is no need to pass a reference when a function is called (that is, the explicit call mentioned in the previous section), and in 5.3 there is a cancel warning if the explicit call is made.

Analysis of the source code
Someone said, "everything is a reference" in PHP.
Look up the PHP source code, in./Zend/zend_compile.c line 1579 has the function definition zend_do_pass_param. (php5.2.13)

Among them is this judgment:
If (original_op == ZEND_SEND_REF &&! CG(allow_call_time_pass_reference)) {print to revoke warnings. }
Basically, you are passing a reference and printing a warning if php.ini's allow_call_time_pass_reference is not.
Looking at where zend_do_pass_param is used, it can be seen that in the parser stage, according to the definition of the element in the structure of parameter ZVAL, whether it is var or value or reference is passed. (php5.2.13./Zend/zend_language_parser.y/c 451/3593)

conclusion
References are like hard links to files in Linux, but unlike Pointers in C, PHP decides whether to pass a reference or a value at the parser stage depending on the context. The call_user_function mentioned in this article does not automatically determine whether to pass a reference or a value. So the previous example call_user_function doesn't work when passing a value, but it gets the right result when passing a reference (but there's also a repeal warning).

Related articles: