php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #32841 returned a member variable cannot be turned into reference
Submitted: 2005-04-26 14:54 UTC Modified: 2005-04-28 10:59 UTC
From: wagner at bonn dot edu Assigned:
Status: Wont fix Package: Scripting Engine problem
PHP Version: 4.3.11, 5.0.4 OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: wagner at bonn dot edu
New email:
PHP Version: OS:

 

 [2005-04-26 14:54 UTC] wagner at bonn dot edu
Description:
------------
When returning a member-variable directly as a reference   
parameter into a function, a fatal error occurs:   
Fatal error: Only variables can be passed by reference ...  
The reproduce code displays the bug (for $case=0) as well 
as two simple workarounds that IMHO show that the 
ZEND-Engine should be able to handle this with no need for 
any error. 
This seems to have been around for a while, at least PHP 
4.3.x  
Probably related to 
http://bugs.php.net/bug.php?id=32840 

Reproduce code:
---------------
$case = 0;

function incr(&$int) {
  return $int++;
}

class foo {
  var $v = 1;
  function &f_ref() { return $this->v; }
  function f_copy() { return (int)$this->v; } //forced copy through type-cast
  function f_default() { return $this->v; }
}

$foo =& new foo();
switch($case) {
 case 0:
  //default behaviour is broken
  echo incr($foo->f_default())."\n";
 case 1:
   //forced reference works AND makes default behaviour work afterwards
   echo incr($foo->f_ref())."\n";
   echo incr($foo->f_default())."\n";
   break;
 case 2:
   //forced copy works
   echo incr($foo->f_copy())."\n";
   break;
}

Expected result:
----------------
incr() should get a copy of $foo->v 

Actual result:
--------------
Fatal error: Only variables can be passed by reference in 
foo.php on line 19 
 

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-04-27 23:45 UTC] tony2001@php.net
Short version: 
this is expected and the error message clearly says why:
only variables can be referenced and you cannot make a reference to an expression result.
Long version:
In your case f_default() returns *copy*, not a reference as you wrongly consider, while f_ref() returns reference and should work indeed.
But I'm a bit surprised to see that f_copy() works, as it should give the same warning as with f_default().
Concerning the case 2, AFAIK it's because of some reference magic: when you return $this->v as reference, it turns in refernce itself (refcount++) and the following call to f_default() returns this reference.
Though, it would be interesting to see what engine gurus say about it.
 [2005-04-28 06:34 UTC] wagner at bonn dot edu
> In your case f_default() returns *copy*, not a reference   
No it doesn't.   
   
Try this as case 1 in the reproduce code as above: 
-------------------------------------------------- 
 case 1:   
   //forced reference works AND makes default behaviour 
   //work afterwards   
   echo incr($foo->f_ref())."\n";   
   echo incr($foo->f_default())."\n";   
   echo incr($foo->f_default())."\n";   
   break;   
   
Expected result:  
----------------  
1  
2  
2  
f_default() should return a copy 
  
Actual result: 
-------------- 
1 
2 
3 
incr() gets a reference to $foo->v and modifies it 
 
Since I filed this behaviour as another bug here 
http://bugs.php.net/bug.php?id=32840 
could it please be looked at too and be unbogusified?
 [2005-04-28 10:59 UTC] alan_k@php.net
What you are trying to do is feasable in  different ways. - just not the way you are trying.. (try the support channels for suggestions.) 
- whether what you are trying to do is a good idea (maintance, code readability, creating bugs....) is another question...

changing the engine behavior to do what you say is extremely complex. And the return on fixing this would not be worth the instability that it would involve (we know from previous efforts at looking at this).

hint: use
return &$this->var; 
$tmp = &$foo->f_default();
incr($tmp);


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 23:01:28 2024 UTC