LoginSignup
3
1

More than 1 year has passed since last update.

【PHP】参照渡しの配列の要素をunsetしても参照は解除されない

Last updated at Posted at 2022-03-22

タイトルの通りです。
参照渡し(参照の代入)が推奨できるかはさておき、挙動の一例として参考にしてください。

テストデータの作成

配列$foodsを作成し、$ref_foodsへ参照を代入します。

$foods = [
    'fruits' => [
        'apple',
        'orange'
    ],
    'vegetables' => [
        'carrot',
        'tomato'
    ]
];

$ref_foods = &$foods;

代入後、$ref_foods$foodsは同じ内容を指します。

var_dump($ref_foods);
/*
array(2) {
  ["fruits"]=>
  array(2) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
  }
  ["vegetables"]=>
  array(2) {
    [0]=>
    string(6) "carrot"
    [1]=>
    string(6) "tomato"
  }
}
*/

var_dump($foods);
/*
array(2) {
  ["fruits"]=>
  array(2) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
  }
  ["vegetables"]=>
  array(2) {
    [0]=>
    string(6) "carrot"
    [1]=>
    string(6) "tomato"
  }
}
*/

配列を丸ごとunsetした場合

unsetされた配列$ref_foodsは未定義の状態になります。
代入元の配列$foodsは変更されません。

unsetのタイミングで参照が解除されることが分かります。

unset($ref_food);

var_dump(isset($ref_food)); // bool(false)
var_dump(isset($food));     // bool(true)

var_dump($foods);
/*
array(2) {
  ["fruits"]=>
  array(2) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
  }
  ["vegetables"]=>
  array(2) {
    [0]=>
    string(6) "carrot"
    [1]=>
    string(6) "tomato"
  }
}
*/

配列の要素をunsetした場合

unsetされた配列の要素$ref_foods['fruits']だけでなく、代入元の配列の要素$foods['fruits']も未定義の状態になります。

unset($ref_foods['fruits']);

var_dump(isset($ref_foods['fruits'])); // bool(false)
var_dump(isset($foods['fruits']));     // bool(false)

$ref_foodsへ要素を代入すると$foodsにも反映されます。
参照が解除されていないことが分かります。

$ref_foods['fruits'][] = 'grape';

var_dump($ref_foods);
/*
array(2) {
  ["vegetables"]=>
  array(2) {
    [0]=>
    string(6) "carrot"
    [1]=>
    string(6) "tomato"
  }
  ["fruits"]=>
  array(1) {
    [0]=>
    string(5) "grape"
  }
}
*/

var_dump($foods);
/*
array(2) {
  ["vegetables"]=>
  array(2) {
    [0]=>
    string(6) "carrot"
    [1]=>
    string(6) "tomato"
  }
  ["fruits"]=>
  array(1) {
    [0]=>
    string(5) "grape"
  }
}
*/

まとめ

公式マニュアルを確認しましたが、根拠になりそうな情報が見つかりませんでした(-_-;)
PHP公式マニュアル: リファレンス渡し
PHP公式マニュアル: リファレンスの解除

参照渡しはコードの見通しが悪くなるので使いたくありませんが、動作を知ることは役に立ちます。
注意点をまとめました。

  • どのように参照が代入されているか(変数をそのままか、一部の要素だけか)
  • 処理の途中でunsetが実行されているか
  • 処理の途中で参照が解除されていないか

2022/03/24追記

記事中のコードでは配列の要素に参照は無いためタイトルの挙動になります。
参照に不慣れだとハマりやすい箇所だと思うので、記事は公開当初のままにしておきます。

参照については、こちらも参考にしてみてください。
Xdebugによる検証方法も掲載されているので、手を動かしながら学べます。
PHP公式マニュアル: 参照カウント法の原理

採用PR

弊社で一緒に働く仲間を募集しています。
全てのオタクを幸せにしたい方、是非ご覧ください!

3
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1