ทำลายวัตถุได้อย่างไร?


120

เท่าที่ฉันรู้ (ซึ่งน้อยมาก) มีสองวิธีดังนี้

$var = new object()

แล้ว:

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

วิธีอื่นที่ดีกว่า? ฉันแยกขนอยู่ที่นี่หรือเปล่า?

คำตอบ:


152

unset()คุณกำลังมองหา

แต่ให้คำนึงว่าคุณไม่สามารถทำลายวัตถุอย่างชัดเจนได้

มันจะยังคงอยู่ที่นั่นอย่างไรก็ตามหากคุณยกเลิกการตั้งค่าวัตถุและสคริปต์ของคุณดัน PHP ไปที่หน่วยความจำ จำกัด วัตถุที่ไม่ต้องการจะถูกเก็บขยะ ฉันจะไปด้วยunset()(ตรงข้ามกับการตั้งค่าเป็น null) เนื่องจากดูเหมือนว่าจะมีประสิทธิภาพที่ดีกว่า (ไม่ได้ทดสอบ แต่บันทึกไว้ในหนึ่งในความคิดเห็นจากคู่มือทางการของ PHP)

ดังที่กล่าวไว้โปรดทราบว่า PHP มักจะทำลายออบเจ็กต์ทันทีที่มีการแสดงเพจ ดังนั้นสิ่งนี้ควรจำเป็นสำหรับการวนซ้ำที่ยาวมาก ๆ และ / หรือหน้าที่มีเนื้อหาเข้มข้นมากเท่านั้น


1
แฟรงกี้ฉันมาจาก C ++ ซึ่งเมื่อเราใช้newครั้งเดียวเราก็ต้องใช้deleteครั้งเดียว สิ่งนี้ไม่เป็นความจริงใน PHP? มีการเก็บขยะอัตโนมัติเมื่อไม่ต้องการวัตถุอีกต่อไป?
gsamaras

3
@gsamaras นั่นคือเรื่องจริง คุณสามารถมีการรั่วไหลได้เช่นกันและคุณควรอ่านเพิ่มเติมเกี่ยวกับ GC ของ php หากคุณกำลังทำ daemons หรือคล้ายกัน ในไซต์ส่วนใหญ่คำขอมีอายุสั้นมากจนไม่สำคัญ php.net/manual/th/features.gc.refcounting-basics.php
Frankie

ไม่unset()เอาการอ้างอิงไปยังวัตถุ?
Yousha Aleayoub

9

โพสต์ที่มีประโยชน์ซึ่งอธิบายความเข้าใจผิดหลายประการเกี่ยวกับเรื่องนี้:

อย่าเรียกผู้ทำลายอย่างชัดเจน

สิ่งนี้ครอบคลุมความเข้าใจผิดหลายประการเกี่ยวกับวิธีการทำงานของตัวทำลาย การเรียกมันอย่างชัดเจนจะไม่ทำลายตัวแปรของคุณตามเอกสาร PHP5:

PHP 5 แนะนำแนวคิด destructor คล้ายกับภาษาเชิงวัตถุอื่น ๆ เช่น C ++ เมธอด destructor จะถูกเรียกใช้ทันทีที่ไม่มีการอ้างอิงอื่น ๆ ไปยังอ็อบเจ็กต์เฉพาะหรือตามลำดับใด ๆ ในระหว่างลำดับการปิดระบบ

โพสต์ด้านบนระบุว่าการตั้งค่าตัวแปรเป็น null สามารถทำงานได้ในบางกรณีตราบเท่าที่ไม่มีสิ่งอื่นใดชี้ไปที่หน่วยความจำที่จัดสรร


2

คำตอบสั้น ๆ : จำเป็นทั้งสองอย่าง

ฉันรู้สึกว่าได้รับคำตอบที่ถูกต้อง แต่ให้น้อยที่สุด โดยทั่วไปแล้วการยกเลิกการตั้งค่า () จะดีที่สุดสำหรับ "ความเร็ว" แต่ถ้าคุณต้องการเรียกคืนหน่วยความจำทันที (ในราคา CPU) ควรใช้ null

เช่นเดียวกับคนอื่น ๆ ที่กล่าวถึงการตั้งค่าเป็น null ไม่ได้หมายความว่าทุกอย่างจะถูกเรียกคืนคุณสามารถมีอ็อบเจ็กต์หน่วยความจำที่ใช้ร่วมกัน (ไม่ได้โคลน) ซึ่งจะป้องกันการทำลายวัตถุ ยิ่งไปกว่านั้นอย่างที่คนอื่น ๆ บอกคุณไม่สามารถ "ทำลาย" วัตถุอย่างชัดเจนได้อยู่ดีดังนั้นคุณไม่ควรพยายามทำมันต่อไป

คุณจะต้องคิดให้ได้ว่าสิ่งไหนดีที่สุดสำหรับคุณ นอกจากนี้คุณยังสามารถใช้ __destruct () สำหรับวัตถุซึ่งจะถูกเรียกว่า unset หรือ null แต่ควรใช้อย่างระมัดระวังและเหมือนที่คนอื่น ๆ กล่าวไว้ว่าห้ามเรียกโดยตรง!

ดู:

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

อะไรคือความแตกต่างระหว่างการกำหนด NULL และ unset?


0

นี่เป็นการพิสูจน์ง่ายๆว่าคุณไม่สามารถทำลายวัตถุได้คุณสามารถทำลายลิงก์ไปยังมันได้เท่านั้น

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

ผลตอบแทน

2

ดูการใช้งานจริงที่นี่: https://eval.in/1054130


3
ขวาคุณได้ทำลายซึ่งคือการอ้างอิงถึง$var2 $varตอนนี้คุณทำลาย$varเช่นกันและสมมติว่าไม่มีการอ้างอิงอื่นใดที่ถืออยู่บนวัตถุคุณทำเสร็จแล้ว
i336_

4
คุณไม่ได้ทำลายวัตถุคุณกำลังทำลายตัวชี้ไปที่วัตถุ มันคือความแตกต่างที่ยิ่งใหญ่
Yevgeniy Afanasyev

1
ในภาษาอื่นคุณสามารถทำลายวัตถุได้และตัวชี้อื่น ๆ ทั้งหมดจะให้ข้อยกเว้นหรือขยะแก่คุณ แต่ไม่ใช่กรณีสำหรับ php
Yevgeniy Afanasyev

1
คุณไม่สามารถทำลาย หากไม่มีสิ่งอ้างอิงที่ถือวัตถุวัตถุนั้นก็พร้อมที่จะรวบรวมโดยตัวเก็บขยะ และคุณไม่สามารถบังคับให้เรียกใช้เครื่องเก็บขยะได้
Daniel

0

อาจอยู่ในสถานการณ์ที่คุณกำลังสร้างวัตถุ mysqli ใหม่

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

แต่ถึงแม้คุณจะปิดวัตถุนั้น

$MyConnection->close();

หากคุณจะใช้print_r()ตรวจสอบเนื้อหา$MyConnectionคุณจะได้รับข้อผิดพลาดดังต่อไปนี้:

Error:
mysqli Object

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

ในกรณีนี้คุณไม่สามารถใช้งานได้unlink()เนื่องจากunlink()จะต้องใช้สตริงชื่อพา ธ แต่ในกรณีนี้$MyConnectionคือ Object

ดังนั้นคุณมีทางเลือกอื่นในการตั้งค่าเป็น null:

$MyConnection = null;

ตอนนี้ทุกอย่างเป็นไปอย่างที่คุณคาดหวัง คุณไม่มีเนื้อหาใด ๆ ภายในตัวแปร$MyConnectionเช่นเดียวกับที่คุณล้างข้อมูล mysqli Object แล้ว

nullมันเป็นวิธีที่แนะนำให้ปิดวัตถุก่อนที่จะตั้งค่าของตัวแปรของคุณไป


-7

ฉันจะไปโดยไม่ได้ตั้งค่าเพราะอาจให้คำใบ้ที่ดีกว่าแก่คนเก็บขยะเพื่อให้หน่วยความจำกลับมาใช้งานได้เร็วขึ้น ระวังว่าสิ่งใด ๆ ที่วัตถุชี้ว่ามีการอ้างอิงอื่นหรือไม่ได้รับการตั้งค่าก่อนมิฉะนั้นคุณจะต้องรอคนเก็บขยะเพราะจะไม่มีการจัดการใด ๆ


16
เว้นแต่คุณจะมีแหล่งข้อมูลสำรองสำหรับคำตอบของคุณคุณอาจไม่ควรโพสต์สิ่งที่คุณคิดว่า "อาจ" เกิดขึ้น ไม่เป็นประโยชน์และนำไปสู่การนำข้อมูลที่ผิดประเภทนี้มาเป็นความจริงซ้ำแล้วซ้ำเล่า
meagar

1
@meagar นั่นคือเหตุผลที่แท้จริงว่าทำไมฉันจึงเชื่อมโยงไปยังหน้าคู่มืออย่างเป็นทางการซึ่งในความคิดเห็นมีตัวอย่างการทดสอบเปรียบเทียบ unset () กับ null
Frankie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.