Smarty (and other tpl ngins): assign and assign_by_ref

后端 未结 3 1813
心在旅途
心在旅途 2021-01-14 16:41

This is not just about Smarty, but I guess most template engines that have variables assigned. It\'s more a theoretical question, than a practical. I have no use case.

相关标签:
3条回答
  • 2021-01-14 17:24

    PHP uses a concept called copy on write. I.e. if you just do a $a = $b PHP will not copy the whole value of $b to $a. It will just create some kind of a pointer. (To be more precise both $a and $b will point to the same zval and it's refcount will be increased.)

    Now, if either $a or $b were modified the value obviously can't be shared anymore and must be copied.

    So, unless you aren't modifying the array in your template code, no copying will be done.

    Some further notes:

    • Beware of trying to optimize your code by blindly inserting references. Often they will have an effect contrary to what you expect. Example to explain why:

      $a = SOMETHING_BIG; // $a points to a zval with refcount 1 and is_ref 0
      $b = $a;            // $a and $b both point to a zval with refcount 2 and is_ref 0
      $c =& $a;           // Now we have a problem: $c can't just point to the same zval
                          // anymore, because that zval has is_ref to 0, but we need one
                          // with is_ref 1. So The zval gets copied. You now have $b
                          // pointing to one zval with refcount 1 and is_ref 0 and $a and
                          // $c pointing to another one with refcount 2 and is_ref 1
      

      So the contrary to what you wanted actually happened. Instead of saving memory you are actually allocating additional. It's often hard to judge whether adding a reference will make it better or worse because it's often hard to trace all different variables pointing to one zval (it's often not as easy as it looks, just have a look at the examples of the debug_zval_dump function. So, really, the only safe way to know, whether a reference is good for performance or not, is to actually profile both variants.

    • Objects are, just like everything else, passed by value in PHP. Still you are right that they behave reference-like, because with objects this value that get's passed around is just a pointer to some other data structure. In most cases the distinction between passing by reference and reference-like behavior isn't of importance, but there still is a difference.

    This was just a short introduction to the topic. You can find a more in-depth analysis of the topic in a blog post by Sara Golemon with the porvoking title "You're being lied to".

    0 讨论(0)
  • 2021-01-14 17:27

    As mentioned in other answers, PHP employs copy-on-write. However I do wish to answer this part of your post:

    Objects are always, automatically assigned by reference.

    This is not entirely true. They are assigned an identifier which points to an object.

    $a = new stdClass();
    $b = $a; // $a and $b now share same identifier
    $b = 0; // $b no longer contains identifier
    var_dump($a); // outputs object
    

    Contrast this with assigning by reference:

    $a = new stdClass();
    $b =& $a; // $a and $b now share same reference
    $b = 0; //
    var_dump($a); // outputs int(0)
    

    Update

    In your edit you ask:

    $a = new BigObject;
    $b = $a; // pointer, right?
    $b->updateSomethingInternally(); // $b is now changed > what about $a?
    

    Did this trigger the copy-on-write? Or are $a and $b still identical (like in ===)?

    Because $b now contains an identifier, i.e. now "points" to same object as $a, $a is also affected. There was never any copying of objects involved.

    0 讨论(0)
  • 2021-01-14 17:35

    PHP uses copy-on-write when passing arrays around, so no extra memory is used until you modify the array. Sorry, no link to back up this claim.

    0 讨论(0)
提交回复
热议问题