ホームページ  >  記事  >  バックエンド開発  >  PHP を慎重に使用する場合の引用理由の分析_PHP チュートリアル

PHP を慎重に使用する場合の引用理由の分析_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-21 15:16:41713ブラウズ

参照型 (Reference) は多くのコンピューター言語で使用されており、非常に強力で実用的な機能として存在します。ポインタに似た実装を持ちますが、ポインタとは異なる動作をします。たとえば、C++ 参照では、逆参照演算子 (*) やメンバーへのポインタ演算子 (->) の面倒な使用をせずに、オブジェクト メンバーを取得するためのドットの直接使用を維持しながら、異なる変数が同じオブジェクトを指すことができます。 Java と C# では、参照がメインの型として直接使用され、開発者はポインターの使用を避けようとします。

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


参照変数には新しい参照を割り当てることができます

C++ では、参照型変数は定義時にのみ参照値を割り当てることができるため、変数の定義をトレースするだけで変数がどのコンテンツを操作するか。

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

コードをコピーします コードは次のとおりです:
$x = 7;

$z = &$x = &$y; x,$ y,$z);


一見すると、$z が $x への参照になり、$z の内容が $y、つまり $x と $z への参照になるように見えます。は $y への参照です。しかし、実際の出力結果は次のとおりです:


コードをコピーします

コードは次のとおりです:
int(21) int(7) int(7)

結果からわかるように、 $x は同じままですが、$z が $y への参照に変更されるだけです。これは、最初に $z 変数の設定を解除してから、新しい値を割り当てることと同じです。


コードをコピーします

コードは次のとおりです:
$z = &$x; $z = &$y; これは実際にはより合理的なロジックです。以下のコードのように、「ポインターがポインターを指す」のような「参照が参照を参照する (参照が参照を参照する)」は取得されず、同じコンテンツ部分を参照する複数の参照変数が取得されるだけです。

コードをコピーします

コードは次のとおりです:

$x = 21;
$z = &$y
配列要素を参照すると、要素 参照型

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

問題のコードを見る前に、最初に指摘しておきます:
配列の代入には常に値のコピーが含まれます。

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

コードは次のとおりです:


$a = array(21, 7);
$b[0] = 7;
echo '
';
var_dump($b);
//array(2) { [0]=> int( 7) } //array(2) { [0]=> int(7) [1]=> int(7) } の要素を参照するとどのような例外が発生するかを見てみましょう。配列。

コードをコピーします

コードは次のとおりです:


$a = array(21, 7);
$c = & $a[0]; ] = " 21";

var_dump($a);
var_dump($b); >' ;
var_dump($c);

'
'// 出力:
// array(2) " 1]= > int(7) }
// array(2) { [0]=> &string(2) "21" [1]=> string(1) "7" } 2) 「21」
コード内の

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

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

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

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

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

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

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

unset($b);
var_dump($a);
//array(2) ) { [ 0]=> string(2) "21" [1]=> int(7) }



PHP 引用符の使用は避けてください

これは実際には、PHP 配列マニュアルに記載されている注意すべき点です。これは、参照を通じて far 配列の値を変更することを希望する foreach で最も頻繁に発生します (この記事を参照)。 実際には、foreach を参照して使用して配列要素の値を変更したいと考えています。これは主に、PHP の配列が連想配列であるためです。この種の配列は「長さが無限で、インデックスが不連続になる可能性があり、文字列と整数が不連続である可能性があります。」同時にインデックスとしても使用されます。」 したがって、for ループを使用して整数インデックスを単純にインクリメントする方法はありません。

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


コードをコピーします

コードは次のとおりです: foreach ($array_var as $key => $value)
$array_var [$key] = $newValue;
参照のもう 1 つの一般的な場所は、関数呼び出しでパラメーターを渡すために参照を使用することです。主な理由は、このメソッドを使用して関数が複数の戻り値を返せるようにするためです。たとえば、関数の実行中にエラーが発生し、戻り値が無効かどうかを表現を使用して示したいとします。

ただし、PHP 関数はさまざまな型を返すことができるため、表現として参照パラメーターを渡す必要はありません。本当に複数の戻り値が必要な場合でも、解決策として「主キーとして文字列を持つ配列」を返すことができますが、各要素がその結果に対応することをドキュメントで指摘する必要がある場合があります。
これを操作するより良い方法は、変数が不要になったときに常に unset を使用して、 コンテンツとの接続を切り替えることです。また、変数が参照型でない場合でも、その変数が使用されていないことを

確認します

。その変数に対して unset を呼び出しても問題はありません。少なくとも、後で変数を再代入しても前の結果に影響を与えないことが保証されます。

PHP 配列への参照によるアクセスに関する問題 - 対称デザイン PHP: 配列要素への参照は危険です – Float Middle 参考文献と foreach - Johannes Schlüter
参考資料の説明 - PHP マニュアル

  1. http://www.bkjia.com/PHPjc/325843.html
www.bkjia.com
tru​​e

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