Reference of variable

Asked

Viewed 1,852 times

2

I am studying PHP and I came across a question of variables by reference and did not understand very well how it behaves.

function foo(&$var) {
   $var++;  
}
$a=5;
foo($a);
echo $a; // Retorna 6

When I saw this function I thought: "Well, but if I make a normal call with return $var++ will also work...

function bar($var) {
   return $var++;
}
$b=5;
bar($b);
echo $b; // Retorna 5

I could not understand very well the behavior and why the first function perform the increment and the second function not.

  • http://php.net/manual/en/language.references.pass.php

  • 1

    @Zoom the first thing I did was look at the documentation and as I did not understand I decided to ask to try to find the explanations in other.

  • Got it, Bro. All right... ! There’ll be a good answer soon.

  • 1

    From what you said, you didn’t quite understand the workings of return, not the references. The return is more important and useful to understand first. No use returning "to anyone".

  • Related http://answall.com/questions/48777/howfunction-a-refer%C3%Aancia-de-vari%C3%A1veis-n%C3%A3o-declares-no-php

  • This tag also has something to do with pass-by-reference

Show 1 more comment

4 answers

7


Simplifying

In this first case, the following happens:

function bar($var) {
   $var++;
   return $var;
}
$b = 5;
echo bar( $b ); // Mostra 6 - valor do return
echo $b;        // Mostra 5 - valor do $b
  • is attached 5 to $b.
  • you call the function bar, passing by the value 5 to her.
  • the value 5 is stored in $var, which is incremented.
  • you give echo in $b, that never ceased to be 5.

See the difference. I used the same variables as the previous case to simplify:

function bar( &$var ) {
   $var++;
   return $var;
}
$b = 5;
echo bar( $b ); // Mostra 6 - valor do return
echo $b;        // Mostra 6 - valor do $b
  • is attached 5 to $b.
  • you call the function bar, passing by the variable $b for her.
    (this happens thanks to &, who took the reference and not the value).
  • $b is the same thing that $var, and incremented.
  • you give echo in $b, which was increased within bar
    (through its "alternative name" $var, which became the name of $bin function).

In short, in the first case, $var is created within the function with value 5. In the second case, $var is $b with a new name.


Complicating

I changed the above examples to use the same variables, and put the increment on a separate line, so as not to fall into this confusion:

function bar( &$var ) {
   return $var++;
}

$b = 5;
echo bar( $b ); // Mostra 5 - valor do return
echo $b;        // Mostra 6 - valor do $b

Notice anything strange? That’s right, look at IDEONE.

The odd result in the first echo has nothing to do with being by reference or not, but with the fact that we are increasing $var AFTER Return. If it were ++$var, the two lines would show 6.

Although not part of the question, I thought it best to comment because if the question function was tested with echo in return, could hinder the understanding.

In short: in this case, we pass $b to the function. In the function we return $var, which is the $b outside the function, i.e., 5. After the return is applied the ++, which increased $b (called $var within the function).

4

The passage by reference I believe to be one of the coolest things that has in the programming.
I believe that one of the questions to be asked when studying this is :

  • Reference to what?

Memoria

Imagine that when you are programming and do a variable assignment : $var = 5;, you are not simply assigning 5 to a variable $var, you are booking a site in the memory of your computer that will have as alias the name $var and he local will possess the value 5.

 0050 | 0051 | 0052 | 0053 | 0054 | 0055 | 0056     <-- possição da memoria
      |      | $var |      |      |      |          <-- alias
      |      |   5  |      |      |      |          <-- valor/referencia

The alias is actually just an access to the contents of the possibility 0052 of memory.

When you generate a passage by reference you are saying that the content of that memory possibility is not a value, but a reference to a location that has the value. It’s a little complicated but it would be basically like this :

$b = &$var;

 0050 | 0051 | 0052 | 0053 | 0054 | 0055 | 0056     <-- possição da memoria
      |      | $var |      |  $b  |      |          <-- alias
      |      |   5  |      | 0052 |      |          <-- valor/referencia

Now when you access $b and will not display 0052, because he’s a reference, it goes up to the reference and get its value in the case 5.

Thus if the content of the possibility 0052 is changed so much $var as $b evening changed. Remembering that you can change both by $var as per $b.

$var = 7;

 0050 | 0051 | 0052 | 0053 | 0054 | 0055 | 0056     <-- possição da memoria
      |      | $var |      |  $b  |      |          <-- alias
      |      |   7  |      | 0052 |      |          <-- valor/referencia

$b = 10;

 0050 | 0051 | 0052 | 0053 | 0054 | 0055 | 0056     <-- possição da memoria
      |      | $var |      |  $b  |      |          <-- alias
      |      |  10  |      | 0052 |      |          <-- valor/referencia

Function

When you generate a function, the variables you create as a parameter generate a possible in memory, if they are not of the reference type, they wait to receive a value, if are of the reference type take the reference of the variable passed.

function teste($a){

}

 0080 | 0081 | 0082 | 0083 | 0084 | 0085 | 0086     <-- possição da memoria
      |      | $a   |      |      |      |          <-- alias
      |      |      |      |      |      |          <-- valor/referencia

teste($var);

 0080 | 0081 | 0082 | 0083 | 0084 | 0085 | 0086     <-- possição da memoria
      |      |  $a  |      |      |      |          <-- alias
      |      |   5  |      |      |      |          <-- valor/referencia


function teste(&$a){

}

 0080 | 0081 | 0082 | 0083 | 0084 | 0085 | 0086     <-- possição da memoria
      |      | $a   |      |      |      |          <-- alias
      |      |      |      |      |      |          <-- valor/referencia

teste($var);

 0080 | 0081 | 0082 | 0083 | 0084 | 0085 | 0086     <-- possição da memoria
      |      |  $a  |      |      |      |          <-- alias
      |      | 0052 |      |      |      |          <-- valor/referencia

Thus $a within the function changes the memory location 0052, changing the content definitively.

  • Better explanation would be impossible, thank you.

  • @Rafaelacioly Thank you :D

  • 1

    The last example would not be teste(&$var);? Remembering that PHP prohibited passing by reference at the time of the call, from the side of who calls.

  • @Guilhermelautert I had misunderstood his example, now I got it right and I will delete the comments here. This error you saw was exactly what I said PHP prohibited.

3

Functions where the parameters have a & means that you must pass a variable with a simple value does not work. Passing by reference means that the passed variable will have its value changed by the function, if it is destroyed within the function and you do some action in it after execution, an error will be generated.

function foo(&$var) {
   $var++;  
}
foo(5);//erro.

Passing argument by value means that variable or value passed will be copied to function and its 'original' will continue unchanged.

Example 1

function porReferencia(&$arg){
    $arg = 'modificado por referência';
}

$argOriginal = 'original';
referencia($argOriginal);
echo $argOriginal; //modificado por referência

Example 2

function porValor($arg){
    $arg = 'modificado por valor';
    return $arg;
}

$arg = 'original';
porValor($arg);
echo $arg; //original

With some exceptions, a function should only modify the values passed as argument(copy) and its internal variables and not variables outside its scope(global), the changes should be returned, so the original content is not lost if it is necessary to uselo or compare it as in example 2

In other languages it is possible to assemble an interesting example where you pass a variable or object to a function/method and inside it destroys the reference, after the call tries to access this variable and a general error saying that the identify never existed.

  • but if I put a variable before the function and change its value after the function, what value will be considered for change?

  • @Rafaelacioly, edition responds to your comment?

1

It took me years to understand why I always avoided using and also because I didn’t understand the practical use in real situations. And also because I wasn’t interested.

I always saw examples with parameters in functions function foo(&$var) { but I didn’t understand why to use it because I can do it using global or static property of a class.

A few years ago I saw a very different and simple usage example using array. That aroused me interest in understanding the use of this parameter resource by reference.

The example with array I saw was something like this:

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

    print_r($arr);

    /*
Array
(
    [0] => a
    [1] => b
    [2] => c
)

    */

    $foo = &$arr[0];
    $foo = 'a modified';

    print_r($arr);

    /*
Array
(
    [0] => a modified
    [1] => b
    [2] => c
)

    */

See how the $foo acts as a reference, that is, as a shortcut (alias) of the array you received in your declaration.

Anything that $foo receive, will be "mirrored" directly in $arr[0].

This makes it much easier to handle multidimensional arrays.

There are other diverse uses, as cited in the other answers.

When thinking of assignments by reference, always imagine a "fake" variable where the value is merely a link in the memory address, ie an alias (shortcut).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.