[PHP] 参照(リファレンス)について

参照(リファレンス)とは、メモリ上のアドレスそのものを代入し、複数の変数を同一のものとして扱うことが出来ます。

ここではPHPのリファレンスについて正しく理解するためにまとめます。

リファレンスの代入

構文

変数の前に「&」を付けると、変数のメモリ上のアドレスであるリファレンスを取得することが出来ます。

&変数

[実装例]リファレンスの代入

コード

以下の例では、変数$aの参照を変数$bに代入し、そのあと変数$bを更新しています。

$a = 1;
$b = &$a;

$b = 2;

var_dump($a, $b);

実行結果

実行すると変数$a、$bどちらも同じように更新されていることが分かります。

$ php test_reference.php
int(2)
int(2)

[実装例]リファレンスの解除

コード

unset関数でリファレンスの解除が出来ます。

$a = 1;
$b = &$a;

unset($b);

$b = 2;

var_dump($a, $b);

実行結果

$ php test_reference.php
int(1)
int(2)

参照渡し

関数やメソッドの引数に、変数の参照を渡してやることが出来ます。

[実装例]参照渡し

コード

以下の例では、関数addVarの引数を参照渡しにして、関数内で$varの値を更新しています。

function addVar(int &$var) {
    $var++;
}

$var = 1;
addVar($var);

var_dump($var);

実行結果

実行結果は、関数の外で宣言された$varの値が更新されていることが分かります。

$ php test_reference.php
int(2)

変数以外を渡すとエラー

参照渡しが設定されている引数に、変数以外の値を直接渡すことはできません。

例えば関数addVarの呼び出しを、

addVar(1);

とすると、以下のエラーが発生します。

$ php test_reference.php

Fatal error: Uncaught Error: addVar(): Argument #1 ($var) cannot be
    passed by reference in .\test_reference.php:16
Stack trace:
#0 {main}
  thrown in .\test_reference.php on line 16

参照返し

クラスのメソッドで返す値を参照に返ることが出来ます。これを参照返しと言います。

構文

参照返しは、メソッドの先頭に「&」を付けることと、呼び出し側でも「&」を付けて呼び出すことで、メソッドの戻り値を参照で受け取ることが出来ます。

function &メソッド名() {
    //
}

[実装例]参照返し

以下の例では、メソッドgetVarが参照返しで定義していて、呼び出し側も参照を受け取る呼び出し方をしています。そのため「$var++」の結果が$testオブジェクトの属性$varに及んでいることが分かります。

コード

class Test {
    private int $var;

    public function __construct(int $var) {
        $this->var = $var;
    }

    public function &getVar() {
        return $this->var;
    }
}

$test = new Test(1);

$var = &$test->getVar();

$var++;

var_dump($test);

実行結果

$ php test_reference.php
object(Test)#1 (1) {
  ["var":"Test":private]=>
  &int(2)
}

参照返しにならないケース

参照返しで定義されているメソッドを、呼び出し側で「&」なしで、以下のように呼び出した場合

$var = $test->getVar();

この場合はリファレンスを受け取れないので、$testオブジェクトの属性$varの値は変わりません。

$ php test_reference.php
object(Test)#1 (1) {
  ["var":"Test":private]=>
  int(1)
}

エラーになるケース

上記とは逆に、参照返しが設定されていないメソッドを、参照を受け取る方法で呼び出した場合は以下のエラーが発生します。

$ php test_reference.php

Notice: Only variables should be assigned by reference in .\test_reference.php on line 37
object(Test)#1 (1) {
  ["var":"Test":private]=>
  int(1)
}

コメント

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)