ホームページ  >  記事  >  バックエンド開発  >  PHP 参照型の使用に関する詳細な説明 (注意)_PHP チュートリアル

PHP 参照型の使用に関する詳細な説明 (注意)_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-13 17:00:10901ブラウズ

PHP 参照は注意して使用してください 参照型 (Reference) は多くのコンピューター言語で使用されており、非常に強力で実用的な機能として存在します。ポインタに似た実装を持ちますが、ポインタとは異なる動作をします。

たとえば、C++ 参照では、逆参照演算子 (*) やメンバーへのポインタ演算子 (->) の面倒な使用をせずに、オブジェクト メンバーを取得するためのドットの直接使用を維持しながら、異なる変数が同じオブジェクトを指すことができます。 Java と C# では、参照がメインの型として直接使用され、開発者はポインターの使用を避けようとします。

参照型は PHP にも導入されており、オブジェクトの割り当てと転送に関しては、基本的に Java/C# と同じ参照転送とみなすことができます (詳細については「オブジェクトと参照」を参照)。しかし同時に、基本型の参照演算子 (&) を使用したコンテンツへの参照の取得もサポートしています。しかし、実際に使用する場合、PHP の参照型は PHP 全体の設計構造に起因する多くの問題を抱えており、プログラムで予期しない結果を引き起こします。

参照変数に新しい参照を割り当てることができます
C++ では、参照型変数には定義時にのみ参照値を割り当てることができるため、変数の定義を辿っていれば、その変数が何を操作しているのかを知ることができます。

しかし、PHP では変数の定義が曖昧であり、変数を定義しなくても使用できます。したがって、変数には参照値を複数回割り当てることができます。

コードは次のとおりです コードをコピー

$x = 21;
$y = 7;

$z = &$x;
$z = &$y;

var_dump($x,$y,$z); 一見すると、$z が $x への参照になり、その後 $z の内容が $y への参照になるように見えます。つまり、$x と $ とします。 z は両方とも $y への参照です。しかし、実際の出力は次のようになります:

コードは次のとおりです コードをコピー

int(21)
int(7)
Int(7) この結果から、$x は変更されませんが、$z は $y への参照に変更されていることがわかります。これは、最初に $z 変数の設定を解除してから、新しい値を割り当てることと同じです。

$z = &$x;
設定を解除($z);
$z = &$y; これは実際にはより合理的なロジックです。たとえば、以下のコードでは、「参照へのポインタ」と同様の「参照への参照」は単なる複数の参照です。同じコンテンツ部分を参照する変数。

$x = 21;
$y = &$x;
$z = &$y

配列要素を参照すると、その要素は参照型になります
変数から参照を取得しても、元の変数の型は変更されませんが、それが配列内の要素である場合は、その要素も参照型に変更されます。

問題のコードを見る前に、最初に指摘すべきことは次のとおりです:

配列の代入には常に値のコピーが含まれます。

配列を参照によってコピーするには、参照演算子を使用します。

つまり、PHP の配列の割り当ては参照ではなくコピーです。割り当てプロセスでは新しい配列が作成され、割り当てられた変数に割り当てられます。新しい変数に対する配列操作は、元の配列変数の内容には影響しません。

$b は、最初の要素を取得するための追加の参照があることを除けば単なる単純な代入ですが、それでも新しい配列をコピーする必要があります。ただし、結果は $b の変更となり、$a の最初の要素も変更されますが、2 番目の要素は影響を受けません。
コードは次のとおりです コードをコピー


$a = 配列(21, 7);
$b = $a;
$b[0] = 7;
var_dump($a);
echo '
';
var_dump($b);

//出力:
//配列(2) { [0]=> int(21) [1]=> int(7) } //array(2) { [0]=> int(7) [1]=> int(7) } 配列内の要素を参照した場合にどのような例外が発生するかを見てみましょう。

$a = 配列(21, 7);
$c = & $a[0];
$b = $a;
$b[0]= "21";
$b[1]= "7";

var_dump($a);

echo '
';
var_dump($b);
echo '
';
var_dump($c);
echo '
';

//出力:

// 配列(2) { [0]=> &string(2) "21" => int(7) } // 配列(2) { [0]=> &string(2) "21" [1]=> 文字列(1) "7" } // string(2) "21"


コード内の
また、出力からは異常なことがわかります。つまり、配列の最初の要素の型に余分な「&」記号が含まれています。そしてこれが参照演算子です。つまり、配列の最初の要素が参照型になります。したがって、割り当ても値のコピーではなく参照コピーになります。

この問題は非常に奇妙で、開発中に多くの不要なトラブルを引き起こしました。当初、コピーされた配列は元の配列に関連していないと考えていましたが、この予期しない参照型のせいで、操作中にも影響を受けました。元の配列。

これが PHP のバグなのか、それとも意図的にこのように設計されているのかはわかりません。長い間オンラインで検索していましたが、この利便性について関連する説明はありません。これについては、Float Middle の「PHP: 配列要素への参照は危険です」と Symmetric Designs の「参照による PHP 配列へのアクセスに関する問題」だけです。 , しかし理由は明かされませんでした。

その後、PHP バグ レポートでいくつかの関連レポート (Bug6417、Bug7412、Bug15025、Bug20993) を確認しました。これはバグであり、後のバージョンでは修正されているという人もいます。詳細はわかりませんが、配列への参照の使用を避けることしかできません。

さらに興味深いのは、これらの参照の設定を解除して 1 つだけを残すと、配列要素は参照のない通常の型になることです。

コードは次のとおりですコードをコピー設定解除($b); unset($c);
var_dump($a);


// 出力:
//配列(2) { [0]=> 文字列(2) "21" => int(7) }


PHP 引用符の使用を避ける
これは実際には、PHP 配列マニュアルで説明されている注意すべき点です。これは、参照を通じて far 配列の値を変更する場合によく発生します (この記事を参照)。

実際には、foreach を参照して使用して配列要素の値を変更したいと考えています。これは主に、PHP の配列が連想配列であるためです。この種の配列は「長さが無限で、インデックスが不連続になる可能性があり、文字列と整数が不連続である可能性があります。」同時にインデックスとしても使用されます。」 したがって、for ループを使用して整数インデックスを単純にインクリメントする方法はありません。

もちろん、以下のコードのように、$key を介して配列要素の値を直接変更することもできますが、これには効率の問題が発生する可能性があります。

コードは次のとおりです コードをコピー
foreach ($array_var as $key => $value)
$array_var [$key] = $newValue;

参照のもう 1 つの一般的な場所は、関数呼び出しでパラメーターを渡すために参照を使用することです。主な理由は、このメソッドを使用して関数が複数の戻り値を返せるようにするためです。たとえば、関数の実行中にエラーが発生し、戻り値が無効かどうかを表現を使用して示したいとします。

ただし、PHP 関数はさまざまな型を返すことができるため、表現として参照パラメーターを渡す必要はありません。本当に複数の戻り値が必要な場合でも、解決策として「主キーとして文字列を持つ配列」を返すことができますが、各要素がその結果に対応することをドキュメントで指摘する必要がある場合があります。

これを行うより良い方法は、コンテンツとの接続を切り替える必要がなくなったときに、変数に対して unset を使用することです。また、変数が参照型でない場合でも、その変数が使用されていないことを確認し、その変数に対して unset を呼び出しても問題ありません。少なくとも、後で変数を再代入しても前の結果に影響を与えないことが保証されます。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/631276.html技術記事参照は慎重に使用する PHP の参照型は多くのコンピューター言語で使用されており、非常に強力で実用的な機能として存在します。ポインタのような実装があります...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。