TL; DR
ก) วิธีการ / ฟังก์ชั่นเพียงอ่านอาร์กิวเมนต์อาเรย์ => การอ้างอิง (ภายใน) โดยนัย
b) วิธีการ / ฟังก์ชั่นปรับเปลี่ยนอาเรย์อาร์กิวเมนต์ => ค่า
ค) เมธอด / ฟังก์ชั่นอาเรย์จะถูกทำเครื่องหมายเป็นการอ้างอิงอย่างชัดเจน => การอ้างอิงที่ชัดเจน (ผู้ใช้ที่ดิน)
หรือสิ่งนี้:
- ไม่ใช่พารามิเตอร์แอมเปอร์แซนด์และพารามิเตอร์ : ผ่านโดยการอ้างอิง; การดำเนินการเขียนแก้ไขสำเนาใหม่ของอาเรย์คัดลอกซึ่งถูกสร้างขึ้นในการเขียนครั้งแรก;
- อาร์เรย์เครื่องหมายแอมเปอร์แซนด์ : ผ่านการอ้างอิง; การดำเนินการเขียนเปลี่ยนอาร์เรย์เดิม
ข้อควรจำ - PHP ทำการคัดลอกค่าเมื่อคุณเขียนไปยังพารามิเตอร์ที่ไม่ใช่เครื่องหมายและแถวลำดับ นั่นคือสิ่งที่copy-on-write
หมายถึง ฉันชอบที่จะแสดงให้คุณเห็นที่มาของพฤติกรรมนี้ แต่ก็น่ากลัวมาก ดีกว่าการใช้xdebug_debug_zval ()
Pascal MARTIN ถูกต้อง Kosta Kontos ยิ่งกว่านั้นอีก
ตอบ
มันขึ้นอยู่กับ.
รุ่นยาว
ฉันคิดว่าฉันเขียนมันลงไปเพื่อตัวเอง ฉันควรมีบล็อกหรืออะไรซักอย่าง ...
เมื่อใดก็ตามที่ผู้คนพูดถึงการอ้างอิง (หรือพอยน์เตอร์สำหรับเรื่องนั้น) พวกเขามักจะจบลงด้วยอาการท้องอืด (ดูที่หัวข้อนี้!)
PHP เป็นภาษาที่น่านับถือฉันคิดว่าฉันควรจะเพิ่มความสับสน (แม้ว่านี่จะเป็นบทสรุปของคำตอบข้างต้น) เพราะถึงแม้ว่าคนสองคนจะพูดถูกในเวลาเดียวกัน แต่คุณก็ยังดีกว่าที่จะตอบโต้ด้วยคำตอบเดียว
ปิดครั้งแรกที่คุณควรรู้ว่าคุณไม่ได้เป็นคนอวดรู้ถ้าคุณไม่ได้คำตอบในลักษณะที่เป็นสีขาวดำและสี สิ่งต่าง ๆ มีความซับซ้อนมากกว่า "ใช่ / ไม่ใช่"
อย่างที่คุณจะเห็นสิ่งทั้งหมดโดยค่า / โดยอ้างอิงมีความเกี่ยวข้องมากกับสิ่งที่คุณกำลังทำกับอาร์เรย์ที่ในขอบเขตวิธีการ / ฟังก์ชั่นของคุณ: อ่านมันหรือแก้ไขมันได้หรือไม่
PHP บอกว่าอะไร? (aka "เปลี่ยนปัญญา")
คู่มือบอกว่านี่ (ผมขอย้ำ):
โดยค่าเริ่มต้นอาร์กิวเมนต์ของฟังก์ชันจะถูกส่งผ่านตามค่า (เพื่อให้ถ้าค่าของอาร์กิวเมนต์ภายในฟังก์ชันนั้นเปลี่ยนไปจะไม่ได้รับการเปลี่ยนแปลงนอกฟังก์ชัน) ในการอนุญาตให้ฟังก์ชั่นในการแก้ไขข้อโต้แย้งของพวกเขาจะต้องผ่านอ้างอิง
เมื่อต้องการให้อาร์กิวเมนต์ของฟังก์ชันผ่านการอ้างอิงเสมอให้ใส่เครื่องหมาย & (&) ไปยังชื่ออาร์กิวเมนต์ในนิยามฟังก์ชัน
เท่าที่ฉันสามารถบอกได้เมื่อผู้เขียนโปรแกรมขนาดใหญ่จริงจังซื่อสัตย์ต่อพระเจ้าพูดถึงการอ้างอิงพวกเขามักจะพูดถึงการเปลี่ยนแปลงค่าของการอ้างอิงนั้น hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
และนั่นคือสิ่งที่พูดถึงคู่มือเกี่ยวกับ:
มีอีกกรณีที่พวกเขาไม่ได้เอ่ยถึง: ถ้าฉันไม่เปลี่ยนแปลงอะไร - แค่อ่าน?
ถ้าคุณส่งอาเรย์ไปยังเมธอดที่ไม่ทำเครื่องหมายการอ้างอิงอย่างชัดเจนและเราจะไม่เปลี่ยนอาเรย์นั้นในขอบเขตฟังก์ชั่น เช่น:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
อ่านต่อไปเพื่อนนักเดินทางของฉัน
PHP ทำอะไรได้จริง? (aka "หน่วยความจำที่ชาญฉลาด")
โปรแกรมเมอร์ตัวใหญ่และจริงจังคนเดียวกันเมื่อพวกเขาจริงจังมากขึ้นพวกเขาพูดถึง "การเพิ่มประสิทธิภาพหน่วยความจำ" ในส่วนที่เกี่ยวกับการอ้างอิง PHP ก็เช่นกัน เพราะPHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
นั่นคือเหตุผลว่าทำไม
มันจะไม่เหมาะที่จะส่งอาร์เรย์ขนาดใหญ่ไปยังฟังก์ชั่นต่างๆและ PHP เพื่อทำสำเนาของพวกเขา (นั่นคือสิ่งที่ "pass-by-value" ทำ)
<?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);
ทีนี้, ถ้านี่คือการส่งผ่านตามค่าจริง, เราอยากได้ 3mb + RAM สักหน่อย, เพราะมีสองชุดของอาร์เรย์, จริงไหม?
ไม่ถูกต้อง. ตราบใดที่เราไม่เปลี่ยน$arr
ตัวแปรที่อ้างอิงหน่วยความจำที่ชาญฉลาด คุณแค่ไม่เห็นมัน นั่นเป็นเหตุผลที่ PHP กล่าวถึง การอ้างอิงผู้ใช้เมื่อพูดถึง&$someVar
เพื่อแยกแยะความแตกต่างระหว่างภายในและชัดเจน (กับแอมเปอร์แซนด์)
ข้อเท็จจริง
ดังนั้น, when an array is passed as an argument to a method or function is it passed by reference?
ฉันมากับสาม (ใช่สาม) กรณี:
a) วิธีการ / ฟังก์ชั่นเพียงอ่านอาร์กิวเมนต์อาเรย์
ข) วิธีการ / ฟังก์ชั่นปรับเปลี่ยนอาร์กิวเมนต์อาเรย์
ค) วิธีการ / ฟังก์ชั่นการโต้แย้งอาร์เรย์ถูกทำเครื่องหมายไว้อย่างชัดเจน เครื่องหมาย)
ก่อนอื่นมาดูกันว่าหน่วยความจำที่อาร์เรย์กินจริง (ทำงานที่นี่ ):
<?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
พารามิเตอร์ถูกส่งผ่านตามค่าจริงคุณจะเห็นบางสิ่งที่คล้ายคลึงกับ1331840
ไบต์ ดูเหมือนว่า$arr
จะมีพฤติกรรมเหมือนเป็นข้อมูลอ้างอิงใช่ไหม นั่นเป็นเพราะมันเป็นข้อมูลอ้างอิง - ข้อมูลภายใน
b) วิธีการ / ฟังก์ชั่นปรับเปลี่ยนอาร์กิวเมนต์อาเรย์
ตอนนี้เรามาเขียนถึงพารามิเตอร์นั้นแทนที่จะอ่านจาก:
<?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);
เดิมพันของฉันคือคุณจะได้รับสูงสุด 200! ดังนั้นกินนี้ประมาณเป็นหน่วยความจำมากที่สุดเท่าที่อ่านจากที่ไม่ใช่เครื่องหมายพระราม