PHP4,5での参照渡しについて具体的な利用方法を教えて下さい。


1. function example() と function &example() は、どういう場合に使いわけるのか?
2. function example($arg) と function example(&$arg) は、どう違うのか?
3. $result = example(); と $result =& example(); の具体的な違い

値渡しは、そのまま値を渡し、参照渡しは、メモリのアドレス?を渡すという程度の理解はしております。しかし、具体的などういう意味で、どういう時に使うのかがピンと来ません。
よくわからないので、自分では値渡ししか利用していませんが、他人のコードの意味がよくわからなかったり、参照渡しのコードが変更できなかったりします。

こんな時にこれを使うという具体例でも構いません。

回答の条件
  • 1人10回まで
  • 登録:2007/04/12 19:25:38
  • 終了:2007/04/19 19:30:03

回答(4件)

id:studioes No.1

studioes回答回数522ベストアンサー獲得回数612007/04/12 19:43:58

ポイント23pt

function func($n){

$n = $n + 1;

}

function funcS(&$n){

$n = $n + 1;

}

$i = 1;

func($i);

echo($i);

funcS($i);

echo($i);

 このコードを動かせばわかると思います。

 参照渡しでは、その変数を関数内で変更すれば、関数外でも値が変更されます。

 戻り値を使うと、一つの関数は一つしか戻せませんね? しかし、複数の変数を同時に変更したい場合があります。 そういった関数の場合に、グローバル変数等を使うことなく、多くの変数を書き換えることが出来るのが参照渡しです。

 また、実装により値渡しよりも参照渡しの方が高速な場合もあります(値渡しでは、メモリ上で値を複製するが、参照渡しでは場所を受け継ぐだけのため、複製する手間が省ける)

id:p_question

2.についての回答ありがとうございます。

複数の変数を同時に変更したい場合、というのがピンと来ないのですが、具体的にはどのような場合なのでしょう?

1と3についても回答をお待ちしております。

2007/04/12 19:58:10
id:studioes No.2

studioes回答回数522ベストアンサー獲得回数612007/04/12 20:38:29

ポイント23pt

 複数の変数を同時に変更したい場合とは、複数の答えを戻す事でもあります。 例えば、idを元に検索して、苗字と名前をそれぞれ得たい場合等には、getName($id,&$first,&$last)の様に定義すると配列にして戻すなどの手間がいらないでしょう?

1と3は以下参照。

http://www.php.net/manual/ja/language.references.php#language.re...

 1と3は密接に関連していて、1は戻り値が参照を戻すと言う表記で、3はそれを参照として$resultに入れます。

 例えば、複数の変数を与えて、その変数の中から必要な変数を選択する関数などは、参照でないと、戻り値(選択された変数)を変更したところで、本来の変数は変更されません。

id:p_question

なんとなくですが、理解できるようになってきました。

getName($id,&$first,&$last)の例に関しては、以下の理解でよろしいですか? 

以下の関数を呼んだ場合、returnしなくても呼び出し側の値($first, $last)が変更される。

function getName($id,&$first,&$last) {

$this->getFirstNameById($id);

$this->getLastNameById($id);

}

>例えば、複数の変数を与えて、その変数の中から必要な変数を選択する関数などは、参照でないと、戻り値(選択された変数)を変更したところで、本来の変数は変更されません。

これは、ちょっと理解できませんでした。

具体的な例で、どのような時にどのような値を渡して、どのような結果を期待しているのかを教えて頂けないでしょうか?

2007/04/13 15:22:45
id:studioes No.3

studioes回答回数522ベストアンサー獲得回数612007/04/13 16:17:34

ポイント22pt

getNameの例は

function getName($id,&$first,&$last) {

$first = '名前';

$last = '苗字';

}

$f = '';

$l = '';

getName(0,$f,$l);

echo($f.$l);

こういう事です。

参照を返すのは

$a = 2;

$b = 3;

$c = 1;

function &selectMax(&$x, &$y, &$z){

$ret =& $x;

if($ret<$y) $ret =& $y;

if($ret<$z) $ret =& $z;

return $ret;

}

$max =& selectMax(&$a,&$b,&$c);

$max += 10;

echo("a:$a, b:$b, c:$c");

 こういう事です(やってる内容は普通やることはない内容ですが、効果はわかるかと思います)

id:p_question

PHP4で実行すると、Call-time pass-by-reference has been deprecatedが3つでますが、以下のようになりました。

a:2, b:13, c:1

なんとなく理解できてきました。ありがとうございました。

2007/04/14 03:00:26
id:gekikawa No.4

gekikawa回答回数110ベストアンサー獲得回数112007/04/14 05:18:25

ポイント22pt

1. function example() と function &example()の使い分け

リファレンスを返す(&付き関数定義)ことは、結合する変数を見付けるために関数を使用したい場合に便利です。と説明されています。

http://q.hatena.ne.jp/1173108302

の2の回答を参照しては?

http://d.hatena.ne.jp/cloned/20060510

こちらもどうぞ

3. $result = example(); と $result =& example(); の具体的な違い

example()がどのように定義されているかによって変わると思いますが、

&付きで定義されていれば、前者は(普通に)値返し、後者は1.のパターン。

&無しで定義されていれば、結果は全く同じで(普通に)値返し。

計算される時にメモリの上でどのように展開されるかが異なる程度でしょう。

と読んだのですがソースが探せませんでした

id:p_question

ありがとうございます。かなり理解できてきました。

function &example する時は、返ってきた値を&で渡さないと (例: $a =& example();) にしないと参照渡しにならないというルールが理解できました。

PHPのマニュアルにある以下の日本語訳は意味がよくわからなかったので、自分で訳しました。

Returning by-reference is useful when you want to use a function to find which variable a reference should be bound to.

元) リファレンスを返すことは、結合する変数を見付けるために関数を使用したい場合に便利です。

新) 参照返しは、参照がどの変数と結びついているのか?を探す関数を使いたい時に便利です。

なんとなくわかる文章になったような…


Unix系OSを使っている僕としては、以下の説明でピンときました。

■値渡し:

% cp hoge foo ($foo = $hoge;)

■参照渡し:

% ln hoge foo ($foo =& $hoge;)


ちなみに他の方が見る際の参考として…

参照渡しだと、値をコピーしないので、メモリーを節約できるというのは、間違いのようですね。PHPが最適化してくれるそうです。

リファレンスを返す

http://www.php.net/manual/ja/language.references.return.php

関数の値渡しと参照渡し、どちらが速い?

http://www.sound-uz.jp/php/test/first2.html

2007/04/17 18:19:24
  • id:kurukuru-neko
    代入操作
    &あり:指定された変数の元の変数を利用する
    &なし:指定された変数のコピーした変数

    functinoの戻り値
    &あり:代入と同様返された値の変数を利用する
        ように指示する
    &なし:指定された変数のコピーした変数
        を使うように指示する

    <?php

    function fn_1() {
    global $gstring;
    return $gstring;
    };

    function &fn_2() {
    global $gstring;
    return $gstring;
    };

    function fn_3($arg) {
    $arg="BBB";
    return $arg;
    };

    function fn_4(&$arg) {
    $arg="BBB";
    return $arg;
    };

    function &fn_5($arg) {
    $arg="BBB";
    return $arg;
    };

    function &fn_6(&$arg) {
    $arg="BBB";
    return $arg;
    };

    function case1() {
    global $gstring;

    print "\nCALL 1\n";
    $gstring = "ABC";
    $call1=fn_1();
    $gstring = "DEF";
    printf("CALL1=%s GSTRING=%s\n",$call1,$gstring);
    $call1="HIJ";
    printf("CALL1=%s GSTRING=%s\n",$call1,$gstring);

    print "\nCALL 2\n";
    $gstring = "ABC";
    $call2=&fn_1();
    $gstring = "DEF";
    printf("CALL2=%s GSTRING=%s\n",$call2,$gstring);
    $gstring ="HIJ";
    printf("CALL2=%s GSTRING=%s\n",$call2,$gstring);

    print "\nCALL 3\n";
    $gstring = "ABC";
    $call3=fn_2();
    $gstring = "DEF";
    printf("CALL3=%s GSTRING=%s\n",$call3,$gstring);
    $gstring ="HIJ";
    printf("CALL3=%s GSTRING=%s\n",$call3,$gstring);

    print "\nCALL 4\n";
    $gstring = "ABC";
    $call4=&fn_2();
    $gstring = "DEF";
    printf("CALL4=%s GSTRING=%s\n",$call4,$gstring);
    $gstring ="HIJ";
    printf("CALL4=%s GSTRING=%s\n",$call4,$gstring);
    };

    function case2() {

    print "\nCALL 21\n";
    $parm = "AAA";
    $call21=fn_3($parm);
    printf("CALL21=%s PARM=%s\n",$call21,$parm);
    $parm = "CCC";
    printf("CALL21=%s PARM=%s\n",$call21,$parm);
    $call21="DDD";
    printf("CALL21=%s PARM=%s\n",$call21,$parm);

    print "\nCALL 22\n";
    $parm = "AAA";
    $call22=&fn_3($parm);
    printf("CALL22=%s PARM=%s\n",$call22,$parm);
    $parm = "CCC";
    printf("CALL22=%s PARM=%s\n",$call22,$parm);
    $call22 = "DDD";
    printf("CALL22=%s PARM=%s\n",$call22,$parm);

    print "\nCALL 23\n";
    $parm = "AAA";
    $call23=fn_4($parm);
    printf("CALL23=%s PARM=%s\n",$call23,$parm);
    $parm = "CCC";
    printf("CALL23=%s PARM=%s\n",$call23,$parm);
    $call23 = "DDD";
    printf("CALL23=%s PARM=%s\n",$call23,$parm);

    print "\nCALL 24\n";
    $parm = "AAA";
    $call24=&fn_4($parm);
    printf("CALL24=%s PARM=%s\n",$call24,$parm);
    $parm = "CCC";
    printf("CALL24=%s PARM=%s\n",$call24,$parm);
    $call24= "DDD";
    printf("CALL24=%s PARM=%s\n",$call24,$parm);

    print "\nCALL 25\n";
    $parm = "AAA";
    $call25=fn_5($parm);
    printf("CALL25=%s PARM=%s\n",$call25,$parm);
    $parm = "CCC";
    printf("CALL25=%s PARM=%s\n",$call25,$parm);
    $call25= "DDD";
    printf("CALL25=%s PARM=%s\n",$call25,$parm);

    print "\nCALL 26\n";
    $parm = "AAA";
    $call26=&fn_5($parm);
    printf("CALL26=%s PARM=%s\n",$call26,$parm);
    $parm = "CCC";
    printf("CALL26=%s PARM=%s\n",$call26,$parm);
    $call26= "DDD";
    printf("CALL26=%s PARM=%s\n",$call26,$parm);

    print "\nCALL 27\n";
    $parm = "AAA";
    $call27=fn_6($parm);
    printf("CALL27=%s PARM=%s\n",$call27,$parm);
    $parm = "CCC";
    printf("CALL27=%s PARM=%s\n",$call27,$parm);
    $call27= "DDD";
    printf("CALL27=%s PARM=%s\n",$call27,$parm);

    print "\nCALL 28\n";
    $parm = "AAA";
    $call28=&fn_6($parm);
    printf("CALL28=%s PARM=%s\n",$call28,$parm);
    $parm = "CCC";
    printf("CALL28=%s PARM=%s\n",$call28,$parm);
    $call28= "DDD";
    printf("CALL28=%s PARM=%s\n",$call28,$parm);
    };

    case1();
    case2();

    ?>

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません