配列であるPHPの経過による価値による。
-
19-09-2019 - |
質問
が配列が引数として渡した方法または機能でした。
うこ:
$a = array(1,2,3);
$b = $a;
は $b
への参照 $a
?
解決
あなたの質問の後半部分については、マニュアルの配列ページを参照してください、これが状態(引用)
配列の割り当ては、常に値を含み、 コピー。への参照演算子を使用します 参照によって配列をコピーします。
そして、与えられた例:
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
// $arr1 is still array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>
最初の部分については、必ずするための最良の方法は試してみることです; - )
このコードの例を考えてみます:
function my_func($a) {
$a[] = 30;
}
$arr = array(10, 20);
my_func($arr);
var_dump($arr);
これは、この出力をあげるます:
array
0 => int 10
1 => int 20
関数がパラメータとして渡された「外」の配列を変更していないことを示し、どの:それはコピーとして渡された、といないの参照
あなたはそれが参照渡したい場合は、、あなたは、このように機能を変更する必要があります:
function my_func(& $a) {
$a[] = 30;
}
出力はなります:
array
0 => int 10
1 => int 20
2 => int 30
この時、のように、アレイは、「参照によって」渡されています。
参考文献を読むことを躊躇しないでくださいマニュアルののセクションについて説明した:それは答える必要がありますご質問のいくつか; - )
他のヒント
あなたの最初の質問に関しては、配列は、参照によって渡されます。あなたがメソッド/関数内の配列を変更しようとすると、そのコピーが最初に行われ、その後、唯一のコピーが変更されます。これは、実際にはそれがないときに、配列は値渡しされるかのように思われてしまう。
は、例えば、この最初のケースでは、あなたがあなたの関数を定義していなくても(パラメータ定義における&文字を使用して)参照することにより$ my_arrayでの受け入れを、それはまだ、参照によって渡されます(例:あなたは「ドン不要なコピーとトンの廃棄物のメモリ)。
function handle_array($my_array) {
// ... read from but do not modify $my_array
print_r($my_array);
// ... $my_array effectively passed by reference since no copy is made
}
あなたは、配列を変更する場合は、しかし、それのコピーが(より多くのメモリを使用していますが、あなたの元の配列が影響を受けないままにする)最初に行われます。
function handle_array($my_array) {
// ... modify $my_array
$my_array[] = "New value";
// ... $my_array effectively passed by value since requires local copy
}
FYI - これは「怠惰なコピー」または「コピーオンライト」として知られている。
。TL;DR
a)の方法/機能 のみを読み込み 配列の引数=> 暗黙の内部参照
b)の方法/機能 変更 配列の引数=> 値
c)メソッド機能の配列引数は明示的に記の参考として(アンパサンド)=> 明示的なユーザからの土)参照
この:
- 非アンパサンド配列param:によっ;の業務を変えるような新しい配列のコピーに対し、コピーが作成された最初の書;
- アンパサンド配列param:によっ;の業務の変更は元の配列になります。
ていきたいと思いPHPな価値をコピー その瞬間を書いてます 非アンパサンド配列param.その copy-on-write
します。プレイしていただければと思いますCソースの行動が怖います。より良い活用 xdebug_debug_zval().
パスカルマでした。Kosta Kontosたにもより一層力を入れています。
答え
それはその時々です。
ロングバージョン
そうなんでこれを書を下ったのは間違いありません。私はブログを持っていっ...
頂く場合の参考文献(またはポインタについているlogomachy(この スレッド!).
PHPている老舗の言語ようと考えたんですが、混乱のもこの決算の概要上記の応答とする。では、二人でできる権利と同時に、いよう割首とについての再考を迫っています。
最初に、知っておきたいこと いないpedantればわからない答えない黒と白に.というよりはかなり複雑なので"yes/no"です。
として見えますが、全体の価値/by-参照のことは関係のようにお願いしまる配列の方法で機能範囲読むことで改変するのですか?
なPHP言うのでしょう。(通称変更"と")
の マニュアル というこの重鉱):
デフォルトでは、関数の引数 渡される値 (いした場合には、 値の引数内での機能 変更, なりま 変更以外の機能)。する機能 修正 その 引数がなければならな によっ.
ての引数は、 機能は常に渡される照会、誤動作防止)、アンパサンド(&)、 引数名、関数の定義
調査を実施しているのは、同じだが、重大な、素直にプログラマー、神話を参考に、通常の話 変更の値を参照する.ことになるなどのマニュアルの話で: hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.
こう場合にはという言葉は使っていないもの:かんだものだ。
どの場合配列方法のない明示的にマークを参考にしなが配列の範囲?E.g.:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
読みに、私のフェローする。
なPHPうか?(通称"メモリ-wise")
同じ大きなプログラマーが大きな問題となっていてもより深刻なものについてのお話のメモリの最適化"についての参照です。でもクリアしました。ので PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
, その なぜ.
ならない理想パスの巨大な配列の様々な機能ならびにPHPのコピーは、保管している"パススルーによる価値"は、すべて):
<?php
// filling an array with 10000 elements of int 1
// let's say it grabs 3 mb from your RAM
$x = array_fill(0, 10000, 1);
// pass by value, right? RIGHT?
function readArray($arr) { // <-- a new symbol (variable) gets created here
echo count($arr); // let's just read the array
}
readArray($x);
こうなると、こうしたパススルーによる、いか3m+RAMがあり 二つの コピーする配列。
間違っています。しなの $arr
変数の参考 メモリ-ワイズ.あなただけなのです。そのたPHP つ ユーザー-地 参考文献 話 &$someVar
, を区別内明(アンパサンド開発にも取りかかっていた。
事実
なので、 when an array is passed as an argument to a method or function is it passed by reference?
が浮かび上がった 三 (えつ)の場合:
a)の方法/機能 のみを読み込み 配列の引数
b)の方法/機能 変更 配列の引数
c)メソッド機能の配列引数は明示的に記の参考として(アンパサンド)
まず、どんな姿を見せてくれるだろうかあなた配列内で実際に食べて実行する こちらの):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
多くのバイトです。ます。
a)の方法/機能 のみを読み込み 配列の引数
今せる機能 のみを読み込み の配列引数としてしっかりメモリの読みロジック間:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
count($arr); // read
$x = $arr[0]; // read (+ minor assignment)
$arr[0] - $arr[1]; // read
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1); // this is 1331840 bytes
printUsedMemory($x);
ねん?80! 下さい.この部分は、PHPマニュアルを省.の場合 $arr
paramが実際に渡される値、まようなもの 1331840
バイトまでとなります。この $arr
のように動作すの参考になったんだと思います。ことになるので は は、参考文献-内です。
b)の方法/機能 変更 配列の引数
今ましょう 書 そのparamくからの読み出し:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
再度、 下さい, が、私にとっては、写っている1331840.この場合、配列の は 実際にコピーされる $arr
.
c)メソッド機能の配列引数は明示的に記の参考として(アンパサンド)
今どんな姿を見せてくれるだろうかいメモリ 書き込み操作を明示的に参照 か行 こちらの)-注、アンパサンド、関数の署名:
<?php
function printUsedMemory(&$arr) // <----- explicit, user-land, pass-by-reference
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
私のベットにあるこの200max!この食べ約してメモリとして からの読み出し、非アンパサンドparam.
デフォルト
- プリミティブを抜いてしまうことが確認された値です。はJavaの文字列は、プリミティブPHP
- アレイのプリミティブを抜いてしまうことが確認された価値
- 物を抜いてしまうことが確認された 参考
配列オブジェクトの経過による価値の配列)が各オブジェクトが参照によって渡される。
<?php $obj=new stdClass(); $obj->field='world'; $original=array($obj); function example($hello) { $hello[0]->field='mundo'; // change will be applied in $original $hello[1]=new stdClass(); // change will not be applied in $original $ } example($original); var_dump($original); // array(1) { [0]=> object(stdClass)#1 (1) { ["field"]=> string(5) "mundo" } }
注意:として最適化、値は渡した参考までにその修飾体内での機能です。の場合は変更される値に渡された参照によりそのコピーはコピーを修正しました。
、それはそうのような、値によって渡されます
function test(&$array) {
$array['new'] = 'hey';
}
$a = $array(1,2,3);
// prints [0=>1,1=>2,2=>3]
var_dump($a);
test($a);
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);
あなたの2番目の質問では、$b
は$a
への参照が、$a
のコピーではありません。
多くの最初の例のように、あなたは、次の手順を実行して$a
を参照することができます:
$a = array(1,2,3);
$b = &$a;
// prints [0=>1,1=>2,2=>3]
var_dump($b);
$b['new'] = 'hey';
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);
このスレッドは少し古いですが、ここで何か私はちょうど出くわします:
このコードを試してみてください。
$date = new DateTime();
$arr = ['date' => $date];
echo $date->format('Ymd') . '<br>';
mytest($arr);
echo $date->format('Ymd') . '<br>';
function mytest($params = []) {
if (isset($params['date'])) {
$params['date']->add(new DateInterval('P1D'));
}
}
http://codepad.viper-7.com/gwPYMwする
$ paramsはパラメータのためのアンプはありません注意してください、まだそれが[「日付」] ARR $の値を変更します。これは本当にここにすべての他の説明と一致し、私が今まで考えていません。
私は$のparams [「日付」]オブジェクトのクローンを作成する場合は、、第二出力された日付は同じまま。私はちょうどそれを文字列に設定した場合、それはどちらかの出力には影響しません。
PHPの配列では、デフォルトで値によって関数に渡されます:
$foo = array(11, 22, 33);
function hello($fooarg) {
$fooarg[0] = 99;
}
function world(&$fooarg) {
$fooarg[0] = 66;
}
hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value
world($foo);
var_dump($foo); // (original array modified) array passed-by-reference
ここで出力されます:
array(3) {
[0]=>
int(11)
[1]=>
int(22)
[2]=>
int(33)
}
array(3) {
[0]=>
int(66)
[1]=>
int(22)
[2]=>
int(33)
}
は参照により明示的に渡されない限り、多次元アレイのサブアレイが値によって渡され、また、回答のいずれかを拡張する。
<?php
$foo = array( array(1,2,3), 22, 33);
function hello($fooarg) {
$fooarg[0][0] = 99;
}
function world(&$fooarg) {
$fooarg[0][0] = 66;
}
hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value
world($foo);
var_dump($foo); // (original array modified) array passed-by-reference
結果は次のとおりです。
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
[1]=>
int(22)
[2]=>
int(33)
}
array(3) {
[0]=>
array(3) {
[0]=>
int(66)
[1]=>
int(2)
[2]=>
int(3)
}
[1]=>
int(22)
[2]=>
int(33)
}