Làm thế nào để phá hủy một đối tượng?


120

Theo như tôi biết (rất ít), có hai cách, được đưa ra:

$var = new object()

Sau đó:

// Method 1: Set to null
$var = null;
// Method 2: Unset 
unset($var); 

Phương pháp khác tốt hơn? Tôi có đang bị chẻ tóc ở đây không?

Câu trả lời:


152

Bạn đang tìm kiếm unset().

Nhưng hãy lưu ý rằng bạn không thể phá hủy một đối tượng một cách rõ ràng.

Nó sẽ ở đó, tuy nhiên nếu bạn bỏ thiết lập đối tượng và tập lệnh của bạn đẩy PHP đến giới hạn bộ nhớ, các đối tượng không cần thiết sẽ được thu gom. Tôi sẽ đồng ý với unset()(trái ngược với việc đặt nó thành null) vì nó có vẻ có hiệu suất tốt hơn (không được thử nghiệm nhưng được ghi lại trên một trong các nhận xét từ hướng dẫn sử dụng PHP chính thức).

Điều đó nói rằng, hãy nhớ rằng PHP luôn hủy các đối tượng ngay sau khi trang được phục vụ. Vì vậy, điều này chỉ cần thiết trên các vòng lặp thực sự dài và / hoặc các trang chuyên sâu nặng.


1
Vì vậy, Frankie, tôi đến từ C ++, nơi khi chúng ta sử dụng newmột lần, sau đó chúng ta phải sử dụng deletemột lần. Điều này không đúng trong PHP? Có thu gom rác tự động khi đối tượng không còn cần thiết?
gsamaras

3
@gsamaras đó là sự thật. Tuy nhiên, bạn cũng có thể bị rò rỉ và bạn nên đọc thêm trên GC của php nếu bạn đang làm daemon hoặc tương tự. Trong phần lớn các trang web, yêu cầu tồn tại quá ngắn nên không thành vấn đề. php.net/manual/en/features.gc.refcounting-basics.php
Frankie

unset()xóa tham chiếu đến Đối tượng không?
Yousha Aleayoub

9

Một bài đăng hữu ích giải thích một số hiểu sai về điều này:

Đừng gọi kẻ hủy diệt một cách rõ ràng

Điều này bao hàm một số quan niệm sai lầm về cách thức hoạt động của trình hủy. Gọi nó một cách rõ ràng sẽ không thực sự phá hủy biến của bạn, theo tài liệu PHP5:

PHP 5 giới thiệu khái niệm hủy tương tự như khái niệm của các ngôn ngữ hướng đối tượng khác, chẳng hạn như C ++. Phương thức hủy sẽ được gọi ngay khi không có tham chiếu nào khác đến một đối tượng cụ thể hoặc theo bất kỳ thứ tự nào trong trình tự tắt.

Bài đăng ở trên nói rằng việc đặt biến thành null có thể hoạt động trong một số trường hợp, miễn là không có gì khác trỏ đến bộ nhớ được cấp phát.


2

Câu trả lời ngắn gọn: Cả hai đều cần thiết.

Tôi cảm thấy như câu trả lời đúng đã được đưa ra nhưng rất ít. Vâng thường unset () là tốt nhất cho "tốc độ", nhưng nếu bạn muốn lấy lại bộ nhớ ngay lập tức (với chi phí của CPU) thì nên sử dụng null.

Giống như những người khác đã đề cập, đặt thành null không có nghĩa là mọi thứ được lấy lại, bạn có thể có các đối tượng được chia sẻ bộ nhớ (chưa mở khóa) sẽ ngăn chặn việc phá hủy đối tượng. Hơn nữa, giống như những người khác đã nói, bạn không thể "phá hủy" các đối tượng một cách rõ ràng, vì vậy bạn không nên cố gắng làm điều đó.

Bạn sẽ cần phải tìm ra cái nào là tốt nhất cho bạn. Ngoài ra, bạn có thể sử dụng __destruct () cho một đối tượng sẽ được gọi là unset hoặc null nhưng nó nên được sử dụng cẩn thận và như những người khác đã nói, không bao giờ được gọi trực tiếp!

xem:

http://www.stoimen.com/blog/2011/11/14/php-dont-call-the-destructor-explicit/

Sự khác biệt giữa việc gán NULL và unset là gì?


0

Đây là một chứng minh đơn giản rằng bạn không thể phá hủy một đối tượng, bạn chỉ có thể phá hủy một liên kết đến nó.

$var = (object)['a'=>1];
$var2 = $var;
$var2->a = 2;
unset($var2);
echo $var->a;

trả lại

2

Xem nó hoạt động tại đây: https://eval.in/1054130


3
Đúng vậy, bạn đã phá hủy $var2một tham chiếu đến $var. Bây giờ bạn cũng phá hủy $varvà giả sử không có tham chiếu nào khác đang giữ đối tượng, bạn đã hoàn tất.
i336_

4
Bạn không phá hủy một đối tượng, bạn đang phá hủy một con trỏ đến đối tượng. Đó là một sự khác biệt lớn.
Yevgeniy Afanasyev

1
Trong các ngôn ngữ khác mà bạn có thể tiêu diệt một đối tượng và tất cả các con trỏ khác sẽ cung cấp cho bạn những ngoại lệ hoặc rác, nhưng nó không phải là một trường hợp cho php
Yevgeniy Afanasyev

1
Bạn không thể phá hủy. Nếu không có tham chiếu nào đang giữ đối tượng, đối tượng đã sẵn sàng được thu thập bởi bộ thu gom rác. Và bạn không thể buộc chạy bộ thu gom rác.
Daniel

0

Có thể trong tình huống bạn đang tạo một đối tượng mysqli mới.

$MyConnection = new mysqli($hn, $un, $pw, $db);

nhưng ngay cả sau khi bạn đóng đối tượng

$MyConnection->close();

nếu bạn sử dụng print_r()để kiểm tra nội dung của $MyConnection, bạn sẽ gặp lỗi như sau:

Error:
mysqli Object

Warning: print_r(): Property access is not allowed yet in /path/to/program on line ..
( [affected_rows] => [client_info] => [client_version] =>.................)

trong trường hợp đó bạn không thể sử dụng unlink()unlink()sẽ yêu cầu một chuỗi tên đường dẫn nhưng trong trường hợp $MyConnectionnày là một Đối tượng.

Vì vậy, bạn có một lựa chọn khác là đặt giá trị của nó thành null:

$MyConnection = null;

bây giờ mọi thứ diễn ra đúng như bạn đã mong đợi. Bạn không có bất kỳ nội dung nào bên trong biến $MyConnectioncũng như bạn đã xóa Đối tượng mysqli.

Bạn nên đóng Đối tượng trước khi đặt giá trị của biến thành null.


-7

Tôi sẽ chọn unset vì nó có thể cung cấp cho trình thu gom rác một gợi ý tốt hơn để bộ nhớ có thể khả dụng trở lại sớm hơn. Hãy cẩn thận rằng bất kỳ thứ nào mà đối tượng trỏ đến hoặc có các tham chiếu khác hoặc không được đặt trước hoặc bạn thực sự sẽ phải đợi trình thu gom rác vì sau đó sẽ không có xử lý nào đối với chúng.


16
Trừ khi bạn thực sự có nguồn để sao lưu câu trả lời của mình, bạn có thể không nên đăng những gì bạn nghĩ "có thể" xảy ra. Nó không hữu ích và dẫn đến loại thông tin sai lệch này được coi là sự thật và lặp đi lặp lại.
Mudgar

1
@meagar đó là lý do chính xác tại sao tôi liên kết đến trang hướng dẫn chính thức, trong đó, trong các nhận xét, có một thử nghiệm mẫu so sánh unset () với null.
Frankie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.