質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

5回答

827閲覧

変数の頭に&を付けた際の動きについて

yukina00235

総合スコア63

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2020/03/25 03:29

先日よりPHPを始めました。
超初心者な質問で恐縮ですが、調べても意味がいまいち把握できないので教えてください。

変数の頭に&があった場合ですが、マニュアルんは
$bar = &$foo; // $fooを$barにより参照

との記載があるのですが意味が理解できません。

$list = array(100, 200, 500);
foreach ($list as &$value){
$value *= 1.05;
}
unset($value);

ここでの&$valueはどういった意味になるのでしょうか?
また、最後のunset($value);についてもお願いいたします。

初歩的な内容ですみません。宜しくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

そんな使い方することは一度もないから覚えなくていい。
https://qiita.com/tadsan/items/74f992dcc48216b571bd

自分で&書くのは無名関数(クロージャ)のuseくらいしかない。

正確には違うけど「C言語のポインタ」を理解してないとPHPの参照の意味も理解できない。
ポインタは初心者が一番躓きやすい鬼門なので初心者は避けていい。
ポインタを理解するにはさらに下層の知識が必要。
底がないのに使う場面は少ないので最初から「覚えなくていい」。

投稿2020/03/25 04:03

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukina00235

2020/03/25 04:33

有難うございます、参考にさせて頂きます。
yambejp

2020/03/25 04:37

foreachでの参照渡しは古いPHPでは使えなかったのが あとから追加された機能です。 ということは開発者サイドでは一定のニーズを想定しているのだと思います
guest

0

ベストアンサー

参照渡しとコピーの挙動の理解

まずは参照渡しそのものを把握する必要があるかと思います。

例えば

PHP

1<?php 2 3$a = "test"; 4$b = &$a; 5 6var_dump($a); 7var_dump($b); 8 9$b = "test_2"; 10 11var_dump($a); 12var_dump($b); 13

こんなコードを実行すると

string(4) "test" //$aの内容 string(4) "test" //$bの内容 string(6) "test_2" //$aの内容。($b = "test_2"によって変更されている) string(6) "test_2" //$bの内容

という感じで、$b = "test_2";によって$aも変更されていることがわかるかと思います。

リファレンスとは? のサンプルコードを一つづつ実行してみて、内容を把握してみてください。
さっと読むならこちらも分かりやすいです

一方で

PHP

1$a = "test"; 2$b = $a;

として場合は$b$aのコピーであり、その後に$bを変更しても$aに影響が出ることはありません。

foreachの挙動の把握

次に、foreachの挙動を把握する必要があります。

PHP

1 2$arr = [1,2,3]; 3 4foreach($arr as $value){ 5 $value = ""; 6} 7 8var_dump($arr);

とすると

array(3) { [0] => int(1) [1] => int(2) [2] => int(3) }

と表示され、$arrが変更されていないことが確認できます。
foreachはループ毎にその値をas $valueにコピーする
という挙動をするからです。

上記のforeachを無理やり自力で書くとこんな感じ

PHP

1$list = [1,2,3]; 2 3 4$value = $list[0]; 5$value = ""; 6$value = $list[1]; 7$value = ""; 8$value = $list[2]; 9$value = ""; 10

この場合$valueはコピーですから、変更しても元の配列の値には影響が出ません。

foreachで参照渡しをした場合の挙動

PHPマニュアルでは
ループの中で配列の要素を直接変更したい場合は、 $value の前に & をつけます。こうすると、変数には リファレンス が代入されることになります。
と記述されているのは
デフォルトだとコピーになるが、&をつけると参照渡しになるので、参照元の変数(=配列の要素)に影響を与えることが出来るよ
という感じの意味です。

PHP

1 2$arr = [1,2,3]; 3 4foreach($arr as &$value){ 5 $value = ""; 6} 7 8var_dump($arr); 9

PHP

1 2$list = [1,2,3]; 3 4 5$value = &$list[0]; 6$value = ""; 7$value = &$list[1]; 8$value = ""; 9$value = &$list[2]; 10$value = ""; 11 12var_dump($list); 13

と同じことになり、$listの各要素が参照によって上書きされる状態になります。


という感じで、最小限のコードを書いて(殆どはPHPマニュアルのサンプルコードで済みます)挙動を確認してみることをお勧めします。

foreachで参照渡しを使わずに配列の値を書き換える方法

PHP

1 2$arr = [1,2,3]; 3 4foreach($arr as $key => $value){ 5 $arr[$key] = ""; 6} 7

PHPにはブロックスコープが存在しないため、$keyにコピーされたインデックスを元の配列と組み合わせることで、元配列を直接参照することが出来ます。

投稿2020/03/25 04:31

tanat

総合スコア18727

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukina00235

2020/04/02 04:32

とてもお詳しい回答ありがとうございます。 完ぺきではないのですが、なんとなく理解が深まりました。
guest

0

やり取り見てると「そこをまだ気にするようなレベルではない」のでスルーしていいです。
たぶんどれだけ本質的な説明を受けても理解はできません。

既に出ている「覚えなくていい」という回答が真です。

ちなみに「あえて使わなければいけないような場面は中々ない」です。私もPHP扱ってそれなりに長いですけど業務で出てきたこと、あったかな。そういうものです。

投稿2020/03/25 04:35

m.ts10806

総合スコア80875

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukina00235

2020/04/02 04:34

ご回答有難うございます。 >>やり取り見てると「そこをまだ気にするようなレベルではない」 本当におっしゃる通りで、初心者ゆえに理解できないことがより深くなっている気がいたします。 覚えなくてもいいという事も、しっくりくる感じです。 実際にこれを解決しなければ進めないといった状況に陥った時に改めて考えてみたいと思います 有難うございます。
guest

0

↓この場合は$valueは配列の値を直接参照するので$valueの値を変更した場合は元の配列の値も変わります。

PHP

1foreach ($list as &$value){

↓この場合は$valueは配列の値のコピーなので$valueの値を変更しても元の配列の値は変わりません。

PHP

1foreach ($list as $value){

最後のunsetは引数の型によって挙動が変わりますが、基本的には変数を削除するものです。
$valueは今後不要になるので削除しておこうという感じでしょうか。
しかしながらループの外でループ変数にアクセスするのは不具合誘発する可能性が高いので
おすすめしません。

投稿2020/03/25 04:30

tabuu

総合スコア2480

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukina00235

2020/03/25 04:37

有難うございます。 >>↓この場合は$valueは配列の値のコピーなので$valueの値を変更しても元の配列の値は変わりません。 なんとなくイメージができたかもしれません、要は元の内容を変えずに、その変数のデータを利用したい場合に使う感じでしょうか?使いどころがあまりイメージはできないですが…。 unsetについても有難うございます。
tabuu

2020/03/25 05:00

>要は元の内容を変えずに、その変数のデータを利用したい場合に使う感じでしょうか? 基本はその通りですが、可読性のことを考慮すると以下のようにする方がよいと思います。 $x= $value * 1.05 $value *= 1.05 の場合は、元の配列の値を書き換えようとしているのか、一時的に変数を再利用しようとしているのか、 他の人が見たり、本人でも時間が経過してから見直したら誤まる可能性が高いです。
guest

0

ちょっと厳密に書くとこう

PHP

1foreach ($list as $num=>&$value){

投稿2020/03/25 03:36

yambejp

総合スコア116724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/03/25 03:38

$list[$num]を$valueに参照渡ししているわけで $valueを1.05倍すると$list[$num]も1.05倍されるということです
yukina00235

2020/03/25 04:16

有難うございます。 $numというのはどこから出てきたものなのでしょうか? $numはキーですか?
yambejp

2020/03/25 04:20

> $numはキーですか? そうです、foreachはキーと値を両方参照できます。 ただ、あくまで今回はイメージしやすくするために 例示しただけで、as $key=>$valはマストな書き方ではありません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問