Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【PHP】【初心者】値渡しと参照渡し

値渡しってなんぞ

関数を呼ぶとき、引数って使いますよね。
このとき、呼び出した先に渡された値は、呼び出し元の変数をコピーして使っています。
つまり、呼び出し先の関数でこの引数を変更しても、呼び出し元にはまったく影響がないということです。

public function start()
{
    $number = 10;

    // 上記の変数を使って関数を呼びます
    $this->oneUp($number);

    echo '3:' , $number, ' 関数の後、呼び出し元の値', PHP_EOL;
}

private function oneUp(int $number)
{
    echo '1:', $number, ' これが関数に渡された値', PHP_EOL;

    $number += 1;

    echo '2:', $number, ' 引数に1を足した値', PHP_EOL;
}

実行結果

1:10 これが関数に渡された値
2:11 引数に1を足した値
3:10 関数の後、呼び出し元の値

「3:」の値が変化していないことから、コピーであることがわかります。
これを値渡しと言います。

値渡しで進める通常の処理

せっかく関数で増やしたんだから呼び出し元でも使いたいよ、というとき、
人は呼び出し元で「別の変数」として受け取ります。

public function start()
{
    $number = 10;

    // 左辺で別変数を指定する
    $oneUpNumber = $this->oneUp($number);

    echo '3:' , $oneUpNumber, ' 関数の後、呼び出し元で受け取った値', PHP_EOL;
}

private function oneUp(int $number)
{
    echo '1:', $number, ' これが関数に渡された値', PHP_EOL;

    $number += 1;

    echo '2:', $number, ' 引数に1を足した値', PHP_EOL;

    // 呼び出し先でもreturnで値を返す
    return $number;
}

実行結果

1:10 これが関数に渡された値
2:11 引数に1を足した値
3:11 関数の後、呼び出し元で受け取った値

こんな感じで、通常は処理を進めます。

参照渡し

ところが、こういった手順を踏まなくても、
呼び出し先で、呼び出し元の値を書き換えてしまう渡し方があります。
それが参照渡しです。

public function start()
{
    $number = 10;

    // 上記の変数を使って関数を呼びます
    $this->oneUp($number);

    echo '3:' , $number, ' 関数の後、呼び出し元の値', PHP_EOL;
}

// 受け取った引数の頭に&をつける
private function oneUp(int &$number)
{
    echo '1:', $number, ' これが関数に渡された値', PHP_EOL;

    $number += 1;

    echo '2:', $number, ' 引数に1を足した値', PHP_EOL;
}

実行結果

1:10 これが関数に渡された値
2:11 引数に1を足した値
3:11 関数の後、呼び出し元の値

関数で受け取った引数の頭に「&」をつけたことで「3:」の値が変化しました。
呼び出し先の関数でも呼び出し元の変数(メモリアドレス)を「参照」しているからです。

ここが大事な注意点

ところが、ソースの中でこういった参照渡しが存在すると、
「あれ、変数の値が途中でいつの間にか変わってる???」
という混乱の元になります。
同じ名前の変数が処理の前後で値が変わっていてしまうと、
そのことに大変気付きにくいので、大災害の火種になりかねません。

関数で値を変えて、それを使いたいのであれば別の変数として受け取りましょう。

ちなみにPHPではオブジェクトはデフォルトで参照渡しです。これも注意しましょう。
追記
デフォルトで参照渡しというのは間違いです。こちらの記事参照。
同じ方の&(リファレンス)の使い方の記事も参考になりました。

hommayade
しろうと
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away