Can arguments be harmful?

4

By default, arguments to a function are passed by the value (that is, if the value of the parameter within the function is changed, it is not changed outside the function). To allow a function to modify its arguments, they must be passed by reference .

To have an argument to a function always passed by reference, we add a E commercial ( & ) to the desired argument in the function of the function, as in the example:

<?php
function something(&$string)
{
    $string .= 'B';
}

$variavel = 'A';

something($variavel );
echo $variavel;//Irá mostrar "AB"

I rarely use referrals in PHP function arguments (not to mention never) because I've never really seen need or advantage.

But I remembered that I once read that the reference use is not "good" (I can not remember where I read it), but I notice that sometimes it is used, I wonder if the use of references in arguments implies some problem or loss of performance?

    
asked by anonymous 10.04.2015 / 01:05

3 answers

3

Harmful, I would say yes

Currently I would say yes, it can be harmful given the way how the whole process unfolds since the release 5.3.0 .

From version 5.3.0, if the function call has & , a warning is issued with:

  

call-time pass-by-reference

From version 5.4.0, the above error has been removed, and we get the fatal error .

Now, this means that we can no longer signal in the code, in the call of a function, that a certain value is being passed as reference, and the reading of the code is difficult. To know, we need to "physically" access the function and observe its arguments.

Doubtful of course because the control is now restricted, giving rise to a greater probability of errors and / or mistakes by the programmer, particularly in projects where several are involved.

Advantages

The only advantage I have ever seen in passing values by reference is that we have a fallback in case something goes wrong well in the code.

Or the other way around, have control variables that are manipulated within "more in" functions of our code, without having to walk back and forth with return everywhere:

$super = 1;

function umControloQualquer(&$super) {

    (int)((int)true==1)+2 ? $super++ : $super=0;
}

umControloQualquer($super);

// 5000 linhas e 20 ficheiros depois...

if ($super>=2)
    echo $super;
else
    echo "Alguma coisa correu mal porque o BuBu deveria ser nível II neste momento!";

Control variable simulation passed by reference to a function that will change the same depending on a check. The example is simplistic, but it mirrors a practical case.

View on Ideone .

    
10.04.2015 / 03:08
3

If the resource exists then there is a reason for its use.

Probably the recommendation not to use is to try optimizations. This can be considered premature optimization, mainly because PHP already does optimization pass the argument by reference when this is useful even though it has no mention to pass by reference. Of course, if the expected semantics are not referenced, optimization is about using the copy- on-write . So an attempt to optimize by passing something by reference may even disrupt this optimization.

I will not repeat what I always say that micro-optimizing PHP is not usually the most productive thing.

Although rare, there may be the problem of getting referrals for references and losing control if overused.

But if the intention is really to go by reference, if you have a good reason to use it, there is no problem. And in fact, it is seldom necessary. Almost always when someone thinks about using a reference, they are probably thinking about performance or not finding a better way to do the same, so the use is wrong.

Almost always when the intention is to go by reference, you should do this with a type that is naturally passed on with this semantics.

But for everything there is reason to use or not to use. Like everything else, use really to know what you're doing, if you understand all the implications. And do not use if you do not know why you are using it. Not everyone understands what happens to the data when you use a reference. It's not so complicated, but it's easy to forget that you're manipulating a reference and this has consequences in every writing done on that variable.

I understand the use of the reference in the argument that is different from the parameter . But after Zuul's response I paid more attention to the example and saw something different.

You have problem yes.

One thing is to say that you want to pass an argument by reference, depending on the title of the question, another thing is to ask in the parameter that the argument is implicitly received by reference. That is, who calls does not know that is passing by reference something that should be passed by value under normal conditions.

But what kind of language does this allow? PHP, of course. And the maintainers of language have been overcome. I did not know but the newer versions made the problem worse.

Making the caller use a reference is not so bad. Think carefully. If the caller is explicitly passing by reference, does he know that this semantic is being used, what harm can it cause? At most, what I mentioned, the programmer does not know what this means.

Then a possibility of language improvement would be to force the call to use the reference in the argument when the parameter was noted to be received by reference.

But what did she do? Prohibited to do this: D This ... is ... in-critical!

There the new versions made the reference impractical for those who like organized, expressive code, code that indicates their intention and does not give rise to the wrong interpretation. Since passing by reference is now implicitly use it if you want to create confusion.

This would be the "right":

<?php
function something(&$string)
{
    $string .= 'B';
}

$variavel = 'A';

something(&$variavel); //<============ Note aqui
echo $variavel;//Irá mostrar "AB"

But this does not compile. The certainty was this to be obligatory. So the "signature" of the call beats with the signature of the function definition. That is, both have the reference.

I'm not saying that careful programmers can not program using implicit references without causing problems. But programmers care about programming in C in Assembly :) What I mean is that PHP should not be a language where you have to have this kind of concern. In fact this specifically, nor C has. In C you have to be explicit.

Of course I'm not talking about the types that are known to be for reference, there is a programmer's knowledge that is easier to understand.

In conclusion, it has legibility problem, yes, but it does not mean that it should not be used at all. I would really avoid it and when I had to use it, I would document it blatantly.

    
10.04.2015 / 01:27
1

This answer only complements;

Summarizing

The rumors about using the &$variavel references refer only when you call the functions and not when you declare them, ie:

This is allowed and valid (as well as useful):

function foo(&$a) {
   $a = 'b';
   return true;
}

This is no longer allowed and issues errors since php5.3:

$a = 'a';
var_dump(foo(&$a));

The problem

The "problem" of using no refers to using the statement functions, such as:

function foo(&$a) {
   $a = array();
}

$test = array();
foo($test);
print_r($test);

But at the moment of calling a function and using the reference, such as:

...
foo(&$test);//Chamando a função
print_r($test);

That is, from the moment of the call (call-time pass-by-reference ), in other words, at the moment of the statement "no" there is problem.

When to use

As already mentioned, the use of references in function arguments is not so useful, but a situation that can be useful would be similar to that of the bool exec($comando, $saida); function, for example:

function foo($a, &$b) {
    $b = array();
    if ($a === 'A') {
        return true;
    }

    return false;
}

Many native PHP functions make use of this, such as rsort , sort , exec , array_walk , preg_match_all , etc.

Another situation we can use is the use of the array_walk function, for example:

function foo(&$item, $key){//Usando referencia em item
   if($key === 'c'){
        $item = 'Tchau';
   }
}

$arr = array('a' => '1', 'b' => '2', 'c' => 'Oi');

array_walk($arr, 'foo');
print_r($arr);

The output will look something like:

array(
    [a] => '1',
    [b] => '2',
    [c] => 'Tchau'
)

Are we required to use this?

At the time we create / declare a function we do not need this (unless you want), you can use other ways to return the value, as a simple return ...; . If you want to return two different data we can use an associative array such as:

function foo($a) {
   ...
   return array(
       'status' => $x, //Retorna boolean
       'message' => $y //Retorna string
   );
}
    
10.04.2015 / 05:25