2

I have a class that contains the following:

class TestClass {
    protected $items = [];

    public function toArray(){
        return $this->items;
    }

    // Items gets set using set(array $items){}
}

In another class I call this:

$tmpList = $list->toArray();

Now if I am not mistaken, this will create a whole new separate array, so if the array in TestClass has 100k items calling toArray() will create another array consisting of another 100k items for two arrays totaling 200k items.

Is there a way for me to just return a reference to the items in TestClass so I have one array with 100k items and $tmpList just references those items?

If I do this to sort the array, the array doesn't change

$tmpList = $list->toArray();
usort($tmpList, function($a, $b) use ($orderBy, $direction){
    if($direction == 'desc'){
        return $b->$orderBy > $a->$orderBy;
    }elseif($direction == 'asc'){
        return $b->$orderBy < $a->$orderBy;
    }
});

If I append this after it:

$list->set($tmpList);

The array gets sorted.

Get Off My Lawn
  • 34,175
  • 38
  • 176
  • 338

2 Answers2

4

No, it will not duplicate the entire array's contents. Items in the array will be handled by reference. PHP will optimise this behind the scenes. PHP is not C. It has no references in the same sense that C does (pointers to memory locations). You do not need to worry about optimising this.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Not Sur. From http://php.net/manual/en/language.types.array.php we have "Array assignment always involves value copying. Use the reference operator to copy an array by reference." – Luc M Mar 01 '16 at 16:07
  • 1
    @Luc *Logically.* That's not about memory-management. – deceze Mar 01 '16 at 16:08
  • @deceze I don't think that this is true... I have a function that will order an array, if I call the `toArray()`, then `usort` on the array, it doesn't get sorted. However, if I do the same thing, then replace the original array it does get sorted. – Get Off My Lawn Mar 01 '16 at 16:21
  • Object references within an array are copied along with the array. Any change to the order of the array does not affect the original array. Changes in any object within the array will be reflected in the original array. However, any changes to a reference in the array copy will not be reflected in the original array. – apokryfos Mar 01 '16 at 16:39
  • I made a function `protected function &arrayRef(){return $this->items;}` I then call it like this: `$tmpList = &$list->arrayRef();` I then don't have to save it back to the array like I had to without using `&`. – Get Off My Lawn Mar 01 '16 at 16:53
  • 1
    @GetOffMyLawn If you want a reference that, when manipulated also manipulated the origin, then use my aproach putting an & in the command. But if you are "only" concerned about performace and data duplication, then deceze is right. Data gets duplicated only on demand which can be often quicker than the very slow reference implementation of PHP. – Torge Mar 01 '16 at 16:53
3
$tmpList = &$list->toArray();

Even though you should test the real performance impact as PHP acts unexpected with using references.

Update: Actualy it seems you also have to add the & infront of the function declaration. Got this part wrong.

public function &toArray(){ ... }
Torge
  • 2,174
  • 1
  • 23
  • 33
  • 2
    That *means* something very different in PHP than "memory optimisation". **Do not use this unless you mean to allow two separate scopes to _manipulate_ the same value.** – deceze Mar 01 '16 at 16:06
  • I made a function `protected function &arrayRef(){return $this->items;}` that does basically the same thing but returns it as a reference and used your assignment method. – Get Off My Lawn Mar 01 '16 at 16:55
  • @GetOffMyLawn Don't complain to me when you get unexpected side effects yet see no real difference in memory consumption... – deceze Mar 01 '16 at 17:27
  • @deceze Unexpected low performance, yes. Have been there. That you have to be careful as always when using references, granted. But unexpected side effects? Never expierienced those. Anything perticular? – Torge Mar 01 '16 at 17:52
  • @Torge When returning an array from a function you usually expect there to be no reference. This can easily lead to code manipulating the array outside the class and unexpectedly changing the array inside the class. Side effect. The sorting should simply be done inside the class. – deceze Mar 01 '16 at 17:58
  • I guess that is why an & is needed on both sides. If you don't specify & as the caller you will not get a reference. I don't see any "unexpected" side effects there. But as I said. Ofc you have to be always carefull when handling references. – Torge Mar 01 '16 at 18:02