关于PHP中的引用传值或返回值总结(英文)
时间:2007-02-17 来源:PHP爱好者
有一段时间一直迷惑于PHP中引用的传递,后来查手册及C源程序,并反复测试,大致对引用传递在内存中的模式有了一定的了解,后来为了加深印象,写了个总结,应该不会有大的问题——当然这是在PHP4中,在以后的版本中可能会有变化。当时写总结的时候,想锻炼一下英语,因此就凑合了一篇。不过本人英语不好,也懒得翻译,反正当时想自己看得懂就行了。今天心血来潮,突然觉得还蛮有用的,于是在这里现丑了,请大家指正。那位看得懂的帮忙翻译一下吧,我没空了。
[code:1:2433d9e506]
<?php
/*
filename: SetGetTest.php
comment on assignment by value and referrence
assuming $var is a varialbe, its handle(pointer) is named as *var,
and its content is named as @var
the memory area of @var is referred by *var, if the *var is the same,
then the memory areas are the same, so *var is just like a pointer.
1. when $var = $var1
@var copied from @var1, but in the different memory area,
new *var assigned by the system, pointing to the memory area holding @var
*var and *var1 are different
2. when $var =& $var1,
*var assigned by *var1, and the @var is not assigned or copied,
it is absolutely the same as @var1, and in the same memory area
both *var and *var1 pointing to the memory area, that means they are the same.
passing by referrence
3.
function set1(&$s){
$var =& $s;
}
set1($var1) results:
*var1 passing to the function, and *s is the same as *var1,
then *var is the same as *s, the result is that *var is the same as *var1
and all the contents are the same obviously.
4.
function set2(&$s){
$var = $s;
}
set2($var1) results:
*var1 passing to the function, and *s is the same as *var1,
but when $var = $s executes, from 1. we can see @var is the same as @s,
but *var is different from *s, so @var and @s is not in the same memory area,
while @s and @var1 is sharing the same memory area, also *var1 and *s are the same.
5.
normal function return:
function get(){ return $var1; }
assuming the result is referred by a variable $result.
then @result is copied from @var1 but *result is not the same as *var1
when $var = get();
first you get a variable $result, as I said above, @result is the same as @var1, but *result
is different from *var1, and next $var = $result executes.
As I said in 1., you can find, @var is the same as @result and the same as @var1,
but *var is different from *result AND *var1;
while $var =& get() just means:
*var is the same as *result, so @var and @result are in the same memory area,
but they are still different from those of $var1,
both the memory area of @var1 and *var1,
6.
returning by referrence
function &get(){ return $var1; }
there are two ways to get the result
$var = get(); and $var =& get(); now I will tell the difference
I. $var = get();
the *result is the same as *var1 and so @result and @var1 are the same.
and then $var = $result executes,
*var is not the same as *result, and also different from *var1,
but their contents are the same.
I. $var =& get();
the *result is the same as *var1 and so @result and @var1 are the same.
and then $var =& $result executes,
this means $var and $result are the same, both of @ and *
*/
// the test is the following
function println($s = ""){
print "$s<br>n";
}
class GetSetTest
{
var $var = null;
function setByRef(&$arg){
$this->var =& $arg;
}
function passByRef(&$arg){
$this->var = $arg;
}
function setByVal($arg){
$this->var = $arg;
}
function &getByRef(){
return $this->var;
}
function getByVal(){
return $this->var;
}
}
$o = new GetSetTest;
println("============ setByRef getByRef =============");
println("-----------------Before change----------------");
$in = "before change";
$o->setByRef($in);
$outByVal = $o->getByRef();
$outByRef =& $o->getByRef();
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println("-----------------After change-----------------");
$in = "after change";
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println();
println("============ setByRef getByVal =============");
println("-----------------Before change----------------");
$in = "before change";
$o->setByRef($in);
$outByVal = $o->getByVal();
$outByRef =& $o->getByVal();
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println("-----------------After change-----------------");
$in = "after change";
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println();
println("============ passByRef getByVal =============");
println("-----------------Before change----------------");
$in = "before change";
$o->passByRef($in);
$outByVal = $o->getByVal();
$outByRef =& $o->getByVal();
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println("-----------------After change-----------------");
$in = "after change";
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println();
/*
以下输出结果是我(夜猫子)擅自编辑添加的,主要是为后来人查看方便加在这里,越肉代庖,向longnetpro致歉
输出结果:
============ setByRef getByRef =============
-----------------Before change----------------
$in: before change
$outByVal: before change
$outByRef: before change
$this->var: before change
-----------------After change-----------------
$in: after change
$outByVal: before change
$outByRef: after change
$this->var: after change
============ setByRef getByVal =============
-----------------Before change----------------
$in: before change
$outByVal: before change
$outByRef: before change
$this->var: before change
-----------------After change-----------------
$in: after change
$outByVal: before change
$outByRef: before change
$this->var: after change
============ passByRef getByVal =============
-----------------Before change----------------
$in: before change
$outByVal: before change
$outByRef: before change
$this->var: before change
-----------------After change-----------------
$in: after change
$outByVal: before change
$outByRef: before change
$this->var: after change
*/
?>
[/code:1:2433d9e506]
夜猫子 回复于:2003-12-17 09:48:54 老兄你经常都发一些要我慢慢看的东西,呵呵,我先收,等闲了来拜读
mikespook 回复于:2003-12-17 11:42:55 呼,好累~~~~没读代码~~~只看了前面的部分~~~
恩,如果能和C++做一个比较就好了~~~~
还有一点我不是很明白~~
$t="123";
funciton &test($t1)
{
$t2 = $t1
return $t2;
}
$t3 =& test($t);
$t, $t1 ,$t2 内存都将在什么时候释放~~
NightKids 回复于:2003-12-17 14:56:35 首先,ZEND 里面定义的两个函数
ZEND_API void start_memory_manager(TSRMLS_D);
ZEND_API void shutdown_memory_manager(int silent, int clean_cache TSRMLS_DC);
PHP5.0b2
在源代码 的 main.c 里面的 php_request_shutdown_for_exec 函数里有
1190 行 开始:
[code:1:8988e926b5]
void php_request_shutdown(void *dummy)
{
TSRMLS_FETCH();
/* EG(opline_ptr) points into nirvana and therefore cannot be safely accessed
* inside zend_executor callback functions.
*/
EG(opline_ptr) = NULL;
zend_try {
zend_exec_finished(TSRMLS_C);
} zend_end_try();
zend_try {
php_end_ob_buffers((zend_bool)(SG(request_info).headers_only?0:1) TSRMLS_CC);
} zend_end_try();
zend_try {
sapi_send_headers(TSRMLS_C);
} zend_end_try();
if (PG(modules_activated)) zend_try {
php_call_shutdown_functions();
} zend_end_try();
if (PG(modules_activated)) {
zend_deactivate_modules(TSRMLS_C);
}
zend_try {
int i;
for (i=0; i<NUM_TRACK_VARS; i++) {
if (PG(http_globals)[i]) {
zval_ptr_dtor(&PG(http_globals)[i]);
}
}
} zend_end_try();
zend_deactivate(TSRMLS_C);
zend_try {
sapi_deactivate(TSRMLS_C);
} zend_end_try();
zend_try {
shutdown_memory_manager(CG(unclean_shutdown), 0 TSRMLS_CC);
} zend_end_try();
zend_try {
zend_unset_timeout(TSRMLS_C);
} zend_end_try();
#ifdef PHP_WIN32
CoUninitialize();
#endif
}
/* }}} */
[/code:1:8988e926b5]
shutdown_memory_manager();
同样 其他方式 结束的时候 也会
调用 shutdown_memory_manager();
也就是说释放是在 php 程序执行完毕,返回结果之后就释放了
php爱好者站 http://www.phpfans.net dreamweaver|flash|fireworks|photoshop.
[code:1:2433d9e506]
<?php
/*
filename: SetGetTest.php
comment on assignment by value and referrence
assuming $var is a varialbe, its handle(pointer) is named as *var,
and its content is named as @var
the memory area of @var is referred by *var, if the *var is the same,
then the memory areas are the same, so *var is just like a pointer.
1. when $var = $var1
@var copied from @var1, but in the different memory area,
new *var assigned by the system, pointing to the memory area holding @var
*var and *var1 are different
2. when $var =& $var1,
*var assigned by *var1, and the @var is not assigned or copied,
it is absolutely the same as @var1, and in the same memory area
both *var and *var1 pointing to the memory area, that means they are the same.
passing by referrence
3.
function set1(&$s){
$var =& $s;
}
set1($var1) results:
*var1 passing to the function, and *s is the same as *var1,
then *var is the same as *s, the result is that *var is the same as *var1
and all the contents are the same obviously.
4.
function set2(&$s){
$var = $s;
}
set2($var1) results:
*var1 passing to the function, and *s is the same as *var1,
but when $var = $s executes, from 1. we can see @var is the same as @s,
but *var is different from *s, so @var and @s is not in the same memory area,
while @s and @var1 is sharing the same memory area, also *var1 and *s are the same.
5.
normal function return:
function get(){ return $var1; }
assuming the result is referred by a variable $result.
then @result is copied from @var1 but *result is not the same as *var1
when $var = get();
first you get a variable $result, as I said above, @result is the same as @var1, but *result
is different from *var1, and next $var = $result executes.
As I said in 1., you can find, @var is the same as @result and the same as @var1,
but *var is different from *result AND *var1;
while $var =& get() just means:
*var is the same as *result, so @var and @result are in the same memory area,
but they are still different from those of $var1,
both the memory area of @var1 and *var1,
6.
returning by referrence
function &get(){ return $var1; }
there are two ways to get the result
$var = get(); and $var =& get(); now I will tell the difference
I. $var = get();
the *result is the same as *var1 and so @result and @var1 are the same.
and then $var = $result executes,
*var is not the same as *result, and also different from *var1,
but their contents are the same.
I. $var =& get();
the *result is the same as *var1 and so @result and @var1 are the same.
and then $var =& $result executes,
this means $var and $result are the same, both of @ and *
*/
// the test is the following
function println($s = ""){
print "$s<br>n";
}
class GetSetTest
{
var $var = null;
function setByRef(&$arg){
$this->var =& $arg;
}
function passByRef(&$arg){
$this->var = $arg;
}
function setByVal($arg){
$this->var = $arg;
}
function &getByRef(){
return $this->var;
}
function getByVal(){
return $this->var;
}
}
$o = new GetSetTest;
println("============ setByRef getByRef =============");
println("-----------------Before change----------------");
$in = "before change";
$o->setByRef($in);
$outByVal = $o->getByRef();
$outByRef =& $o->getByRef();
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println("-----------------After change-----------------");
$in = "after change";
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println();
println("============ setByRef getByVal =============");
println("-----------------Before change----------------");
$in = "before change";
$o->setByRef($in);
$outByVal = $o->getByVal();
$outByRef =& $o->getByVal();
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println("-----------------After change-----------------");
$in = "after change";
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println();
println("============ passByRef getByVal =============");
println("-----------------Before change----------------");
$in = "before change";
$o->passByRef($in);
$outByVal = $o->getByVal();
$outByRef =& $o->getByVal();
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println("-----------------After change-----------------");
$in = "after change";
println("$in: ".$in);
println("$outByVal: ".$outByVal);
println("$outByRef: ".$outByRef);
println("$this->var: ".$o->var);
println();
/*
以下输出结果是我(夜猫子)擅自编辑添加的,主要是为后来人查看方便加在这里,越肉代庖,向longnetpro致歉
输出结果:
============ setByRef getByRef =============
-----------------Before change----------------
$in: before change
$outByVal: before change
$outByRef: before change
$this->var: before change
-----------------After change-----------------
$in: after change
$outByVal: before change
$outByRef: after change
$this->var: after change
============ setByRef getByVal =============
-----------------Before change----------------
$in: before change
$outByVal: before change
$outByRef: before change
$this->var: before change
-----------------After change-----------------
$in: after change
$outByVal: before change
$outByRef: before change
$this->var: after change
============ passByRef getByVal =============
-----------------Before change----------------
$in: before change
$outByVal: before change
$outByRef: before change
$this->var: before change
-----------------After change-----------------
$in: after change
$outByVal: before change
$outByRef: before change
$this->var: after change
*/
?>
[/code:1:2433d9e506]
夜猫子 回复于:2003-12-17 09:48:54 老兄你经常都发一些要我慢慢看的东西,呵呵,我先收,等闲了来拜读
mikespook 回复于:2003-12-17 11:42:55 呼,好累~~~~没读代码~~~只看了前面的部分~~~
恩,如果能和C++做一个比较就好了~~~~
还有一点我不是很明白~~
$t="123";
funciton &test($t1)
{
$t2 = $t1
return $t2;
}
$t3 =& test($t);
$t, $t1 ,$t2 内存都将在什么时候释放~~
NightKids 回复于:2003-12-17 14:56:35 首先,ZEND 里面定义的两个函数
ZEND_API void start_memory_manager(TSRMLS_D);
ZEND_API void shutdown_memory_manager(int silent, int clean_cache TSRMLS_DC);
PHP5.0b2
在源代码 的 main.c 里面的 php_request_shutdown_for_exec 函数里有
1190 行 开始:
[code:1:8988e926b5]
void php_request_shutdown(void *dummy)
{
TSRMLS_FETCH();
/* EG(opline_ptr) points into nirvana and therefore cannot be safely accessed
* inside zend_executor callback functions.
*/
EG(opline_ptr) = NULL;
zend_try {
zend_exec_finished(TSRMLS_C);
} zend_end_try();
zend_try {
php_end_ob_buffers((zend_bool)(SG(request_info).headers_only?0:1) TSRMLS_CC);
} zend_end_try();
zend_try {
sapi_send_headers(TSRMLS_C);
} zend_end_try();
if (PG(modules_activated)) zend_try {
php_call_shutdown_functions();
} zend_end_try();
if (PG(modules_activated)) {
zend_deactivate_modules(TSRMLS_C);
}
zend_try {
int i;
for (i=0; i<NUM_TRACK_VARS; i++) {
if (PG(http_globals)[i]) {
zval_ptr_dtor(&PG(http_globals)[i]);
}
}
} zend_end_try();
zend_deactivate(TSRMLS_C);
zend_try {
sapi_deactivate(TSRMLS_C);
} zend_end_try();
zend_try {
shutdown_memory_manager(CG(unclean_shutdown), 0 TSRMLS_CC);
} zend_end_try();
zend_try {
zend_unset_timeout(TSRMLS_C);
} zend_end_try();
#ifdef PHP_WIN32
CoUninitialize();
#endif
}
/* }}} */
[/code:1:8988e926b5]
shutdown_memory_manager();
同样 其他方式 结束的时候 也会
调用 shutdown_memory_manager();
也就是说释放是在 php 程序执行完毕,返回结果之后就释放了
php爱好者站 http://www.phpfans.net dreamweaver|flash|fireworks|photoshop.
相关阅读 更多 +