TL; DR
a) phương thức / hàm chỉ đọc tham số mảng => tham chiếu ẩn (bên trong)
b) phương thức / hàm sửa đổi đối số mảng => giá trị
c) đối số mảng phương thức / hàm được đánh dấu rõ ràng là tham chiếu (có dấu và) => tham chiếu rõ ràng (đất sử dụng)
Hoặc này:
- param-mảng không ampersand : được truyền bằng tham chiếu; các hoạt động viết thay đổi một bản sao mới của mảng, bản sao được tạo ra trong lần ghi đầu tiên;
- ampersand mảng param : thông qua tham chiếu; các hoạt động viết thay đổi mảng ban đầu.
Hãy nhớ rằng - PHP thực hiện sao chép giá trị thời điểm bạn viết vào tham số mảng không phải là dấu và. Đó là những gì copy-on-write
có nghĩa. Tôi muốn cho bạn thấy nguồn C của hành vi này, nhưng nó đáng sợ ở đó. Sử dụng tốt hơn xdebug_debug_zval () .
Pascal MARTIN đã đúng. Kosta Kontos thậm chí còn hơn thế.
Câu trả lời
Nó phụ thuộc.
Phiên bản dài
Tôi nghĩ rằng tôi đang viết điều này cho bản thân mình. Tôi nên có một blog hoặc một cái gì đó ...
Bất cứ khi nào mọi người nói về các tài liệu tham khảo (hoặc con trỏ, cho vấn đề đó), họ thường kết thúc trong một logisticy (chỉ cần nhìn vào chủ đề này !).
PHP là một ngôn ngữ đáng kính, tôi nghĩ rằng tôi nên thêm vào sự nhầm lẫn (mặc dù đây là một bản tóm tắt các câu trả lời ở trên). Bởi vì, mặc dù hai người có thể đúng cùng một lúc, tốt hơn hết là bạn chỉ nên đập đầu vào một câu trả lời.
Trước hết, bạn nên biết rằng bạn không phải là một người bán hàng nếu bạn không trả lời theo cách thức trắng đen . Mọi thứ phức tạp hơn "có / không".
Như bạn sẽ thấy, toàn bộ điều theo giá trị / tham chiếu có liên quan rất nhiều đến chính xác những gì bạn đang làm với mảng đó trong phạm vi phương thức / hàm của bạn: đọc nó hoặc sửa đổi nó?
PHP nói gì? (còn gọi là "thay đổi khôn ngoan")
Các nhãn hiệu nói này (tôi nhấn mạnh):
Theo mặc định, các đối số hàm được truyền theo giá trị (để nếu giá trị của đối số trong hàm bị thay đổi , nó không bị thay đổi bên ngoài hàm). Để cho phép một hàm sửa đổi các đối số của nó, chúng phải được truyền bằng tham chiếu .
Để có một đối số cho một hàm luôn được truyền bằng tham chiếu, hãy thêm một dấu và (&) vào tên đối số trong định nghĩa hàm
Theo như tôi có thể nói, khi các lập trình viên lớn, nghiêm túc, trung thực với Chúa nói về các tài liệu tham khảo, họ thường nói về việc thay đổi giá trị của tài liệu tham khảo đó . Và đó chính xác là những gì hướng dẫn sử dụng nói về : hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.
Có một trường hợp khác mà họ không đề cập đến, mặc dù: nếu tôi không thay đổi bất cứ điều gì - chỉ cần đọc?
Điều gì xảy ra nếu bạn truyền một mảng cho một phương thức không đánh dấu rõ ràng một tham chiếu và chúng ta không thay đổi mảng đó trong phạm vi hàm? Ví dụ:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
Đọc tiếp, bạn đồng hành của tôi.
PHP thực sự làm gì? (còn gọi là "trí nhớ khôn ngoan")
Các lập trình viên lớn và nghiêm túc tương tự, khi họ thậm chí còn nghiêm túc hơn, họ nói về "tối ưu hóa bộ nhớ" liên quan đến các tài liệu tham khảo. PHP cũng vậy. Bởi vì PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
, đó là lý do .
Sẽ không lý tưởng khi truyền các mảng HUGE cho các hàm khác nhau và PHP để tạo các bản sao của chúng (rốt cuộc đó là "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);
Bây giờ, nếu điều này thực sự là giá trị truyền qua, chúng ta sẽ có một số RAM 3mb +, bởi vì có hai bản sao của mảng đó, phải không?
Sai lầm. Miễn là chúng ta không thay đổi $arr
biến số, đó là một tài liệu tham khảo, thông minh về trí nhớ . Bạn không nhìn thấy nó. Đó là lý do tại sao PHP đề cập đến các tham chiếu đất người dùng khi nói về &$someVar
, để phân biệt giữa các tham chiếu nội bộ và rõ ràng (với ký hiệu và).
Sự kiện
Vì thế, when an array is passed as an argument to a method or function is it passed by reference?
Tôi đã đưa ra ba trường hợp (yeah, ba):
a) phương thức / hàm chỉ đọc đối số mảng
b) phương thức / hàm sửa đổi đối số mảng
c) đối số mảng phương thức / hàm được đánh dấu rõ ràng là tham chiếu (với một ký hiệu)
Đầu tiên, chúng ta hãy xem mảng đó thực sự ăn bao nhiêu bộ nhớ (chạy ở đây ):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
Đó là nhiều byte. Tuyệt quá.
a) phương thức / hàm chỉ đọc đối số mảng
Bây giờ chúng ta hãy tạo một hàm chỉ đọc mảng đã nói dưới dạng đối số và chúng ta sẽ thấy logic đọc chiếm bao nhiêu bộ nhớ:
<?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);
Muốn đoán không? Tôi nhận được 80! Xem cho chính mình . Đây là phần mà hướng dẫn sử dụng PHP bỏ qua. Nếu thông số $arr
thực sự được truyền qua giá trị, bạn sẽ thấy một cái gì đó tương tự như 1331840
byte. Có vẻ như $arr
hành xử như một tài liệu tham khảo, phải không? Đó là bởi vì nó là một tài liệu tham khảo - một nội bộ.
b) phương thức / hàm sửa đổi đối số mảng
Bây giờ, hãy viết cho param đó, thay vì đọc từ nó:
<?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);
Một lần nữa, xem cho chính mình , nhưng, đối với tôi, đó là khá gần là 1331840. Vì vậy, trong trường hợp này, mảng được thực sự được sao chép vào $arr
.
c) đối số mảng phương thức / hàm được đánh dấu rõ ràng là tham chiếu (với dấu và)
Bây giờ chúng ta hãy xem có bao nhiêu bộ nhớ hoạt động ghi vào một tham chiếu rõ ràng (chạy ở đây ) - lưu ý dấu và trong chữ ký hàm:
<?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);
Đặt cược của tôi là bạn nhận được tối đa 200! Vì vậy, điều này ăn khoảng bộ nhớ nhiều như đọc từ một thông số không ampersand .