引擎盖下的PHP行为

I was just wondering how PHP works under the hood in this certain scenario. Let's say I have these two pieces of code:

function foo() {
    return 2 * 2;
}

// First.
if (foo()) {
    bar(foo());
}

// Second.
if (($ref = foo())) {
    bar($ref);
}

Now the questions:

  1. In the first case, does PHP make some sort of temporary variable inside the if clause? If so, isn't the second piece of code always better approach?

  2. Does the second case take more memory? If answer to the first question is yes to the first question, then not?

  1. In the first case, you are calling a function twice, so, if the function is time consuming, it is inefficient. The second case is indeed better since you are saving the result of foo().

  2. In both cases, PHP needs to allocate memory depending on what data foo() generates. That memory will be freed by the garbage collector later on. In terms of memory both cases are pretty much equivalent. Maybe the memory will be released earlier, maybe not, but most likely you won't encounter a case where it matters.

PHP can't make any temporary variable because it can't be sure that foo()'s returning value will always be the same. microtime(), rand() will return different values for each call, for example.

In the second example, it takes indeed more memory, since PHP needs to create and keep the value in memory.

Here is how to test it :

<?php

function foo() {
    return true;
}

function bar($bool) {
    echo memory_get_usage();
}

if (1) {
    // 253632 bytes on my machine
    if (foo()) {
        bar(foo());
    }
} else {
    // 253720 bytes on my machine
    if (($ref = foo())) {
        bar($ref);
    }
}

The two codes are not equivalent, because the first one calls foo() twice (if it returns a truthy value). If it has side effects, such as printing something, they will be done twice. Or if it's dependent on something that can change (e.g. the contents of a file or database), the two calls may return different values. In your example where it just multiplies two numbers, this doesn't happen, but it still means it has to do an extra multiplication, which is unnecessary.

The answer to your questions is:

  1. Yes, it needs to hold the returned value in a temporary memory location so it can test whether it's true or not.

  2. Yes, it uses a little more memory. In the first version, the temporary memory can be reclaimed as soon as the if test is completed. In the second version, it will not be reclaimed until the variable $foo is reassigned or goes out of scope.