If you have a function that builds a large variable and returns it.. does it make to copies of the large variable and its data? Or is there some sort of referencing going on?

For example:

<?php

function grabData () {

$ f_var = do soemthing that builds a large var;

return $f_var;

}

$m_var = grabData();

?>

If $ f_var is 1mb does that mean I am now taking up 2mb off ram?

    For a little while, yes. But as you return from the function, $f_var goes out of scope and will be garbage collected.

    Still, you might return a reference instead

    function &grabData() {
    	//...
    }

      Actually, in PHP 5, I expect that return to result in just the return of a reference (as in a low-powered pointer). As such, what will be garbage collected is the local reference to the object; the expensive to copy object itself will neither be copied nor garbage collected (until later when $m_var and other associated reference variables are destroyed). Thus, there is no need to return by reference.

        Why do you expect that laserlight? If it does, I need to read up on this.

        Anyway, would you care to explain, or tell me where to find this info. The php.net page on return by reference seem to indicate otherwise to me.

        Also, if you put things in the context of a class (horrible since it breaks encapsulation, but still)

        class a {
        	private $var;
        
        public function a() {
        	$this->var = 'long string';
        }
        
        public function getVal() {
        	return $this->var;
        }
        public function &getRef() {
        	return $this->var;
        }
        }
        
        $a = new a();
        
        $var = $a->getVal();
        $ref = &$a->getRef();
        $notRef = $a->getRef();
        echo 'member: ' . $a->getVal()  . PHP_EOL;
        
        $var = 4;
        echo PHP_EOL . 'assign to var: ' . $a->getVal()  . PHP_EOL;
        
        $notRef = 4;
        echo PHP_EOL . 'assign to notRef: ' . $a->getVal()  . PHP_EOL;
        
        $ref = 'changed';
        echo PHP_EOL . 'assign to ref: ' . $a->getVal()  . PHP_EOL;
        

        And the output:

        member: long string
        assign to var: long string
        assign to notRef: long string
        assign to ref: changed 
        
          johanafm wrote:

          Anyway, would you care to explain, or tell me where to find this info.

          The PHP manual's page on objects and references has the information that you seek.

          johanafm wrote:

          The php.net page on return by reference seem to indicate otherwise to me.

          On the contrary, it recommends quite clearly: "Do not use return-by-reference to increase performance. The engine will automatically optimize this on its own. Only return references when you have a valid technical reason to do so."

          In PHP 4, this was not true. A deep copy would otherwise be performed, so returning by reference was a valid optimisation technique.

          johanafm wrote:

          Also, if you put things in the context of a class

          Try this instead:

          <?php
          class a {
              private $var;
          
          public function a() {
              $this->var = new b('original');
          }
          
          public function getVal() {
              return $this->var;
          }
          
          public function &getRef() {
              return $this->var;
          }
          }
          
          class b {
              private $x;
          
          public function __construct($x) {
              $this->x = $x;
          }
          
          public function transmogrify() {
              $this->x = 'transmogrified';
          }
          
          public function __toString() {
              return $this->x;
          }
          }
          
          $a = new a();
          
          $var = $a->getVal();
          $ref = &$a->getRef();
          $notRef = $a->getVal();
          echo 'member: ' . $a->getVal() . PHP_EOL;
          
          $var = new b('new');
          echo PHP_EOL . 'assign to var: ' . $a->getVal() . PHP_EOL;
          
          $notRef->transmogrify();
          echo PHP_EOL . 'transmogrify notRef: ' . $a->getVal() . PHP_EOL;
          
          $ref = new b('brand new');
          echo PHP_EOL . 'assign to ref: ' . $a->getVal() . PHP_EOL;

          EDIT:
          Notice that I changed $notRef to hold the return value of $a->getVal(). So, we see that assigning new b('new') to $var caused the reference variable to hold a reference to a new object, thus there is no change to $a's b object. On the other hand, calling transmogrify() on $notRef caused $a's b object to change because $notRef holds a reference to the same object as the one contained in $a. But assigning to $ref caused $a's b object to change as well... except that it is a change of object, not just of the object's contents, since $ref is an alias for $a's b object.

            Thanks for the feedback. But I'm still not convinced the return by reference holds for the initial question. If you consider

            class b {
            	private $arr;
            
            public function b() {
            	$this->arr = array('a', 'b', 'c');
            }
            
            public function transformArr() { $this->arr[0] = 1; }
            public function printArr() { print_r($this->arr); echo '<br/>'; }
            
            }
            class a {
            	private $arr;
            	private $b;
            
            public function a() {
            	$this->b = new b();
            	$this->arr = array('a', 'b', 'c');
            }
            
            public function getArr() { return $this->arr; }
            public function getB() { return $this->b; }
            public function printArr() { print_r($this->arr); echo '<br/>'; }
            public function printBArr() { $this->b->printArr(); }
            }
            
            $a = new a();
            
            $arr = $a->getArr();
            $a->printArr();
            $arr[0] = 1;
            $a->printArr();
            
            echo '<br/>';
            $b = $a->getB();
            $a->printBArr();
            $b->transformArr();
            $a->printBArr();
            

            $a->getB() obviously returns a reference to a's instance of b.
            However, $a->getArr() does not provide a reference to a's array.

            Or am I missing something else here?

              johanafm wrote:

              However, $a->getArr() does not provide a reference to a's array.

              Or am I missing something else here?

              You are not missing anything. Note that the PHP manual talks about references to objects of class types being held by the corresponding variables. Values of primitive types, presumably including strings and array types, continue to be held as actual values rather than through a reference.

              johanafm wrote:

              But I'm still not convinced the return by reference holds for the initial question.

              In that sense, yes, it might not hold, because screative's example is not actual code, so we are left guessing. Maybe the "large variable" is just an integer of about one billion (i.e., it can be represented in a 32-bit integer type), in which case there was no problem in the first place. I guessed that a "large variable" means an expensive to copy object, as opposed to a "large array".

                EDIT: I wish I knew how to delete my post....

                  Write a Reply...