วิธีป๊อปของรายการที่เชื่อมโยงโดยใช้ unique_ptr
ฉันกำลังดูการใช้งานรายการที่เชื่อมโยงเดี่ยวโดยใช้unique_ptr
onhttps://solarianprogrammer.com/2019/02/22/cpp-17-implementing-singly-linked-list-smart-pointers/. คำถามของฉันเกี่ยวข้องกับวิธีการต่อไปนี้:
3 struct List {
4 List() : head{nullptr} {};
5
6 // ...
7
8 void pop() {
9 if(head == nullptr) {
10 return;
11 }
12
13 std::unique_ptr<Node> temp = std::move(head);
14 head = std::move(temp->next);
15 }
16
17 // ...
18 };
ฉันสงสัยว่าทำไมต้องใช้ชั่วคราวที่นี่? ทำไมคุณทำhead = std::move(head->next)
ไม่ได้? เป็นเพราะมันจะส่งผลให้หน่วยความจำรั่วหรือเปล่า? เมื่อhead
ถูกกำหนดใหม่จะunique_ptr
ทำให้หน่วยความจำปัจจุบันถูกชี้ไปโดยอัตโนมัติหรือไม่?
ฉันรู้สึกว่าตัวชี้อัจฉริยะเป็นหลักฐานที่โง่เขลาจากการรั่วไหลของหน่วยความจำ ดูเหมือนว่าในกรณีนี้อาจมีการรั่วไหลของหน่วยความจำสำหรับต้นฉบับhead
เนื่องจากจะไม่มีตัวชี้อัจฉริยะชี้ไปที่มันอีกต่อไป?
คำตอบ
ฉันสงสัยว่าทำไมต้องใช้ชั่วคราวที่นี่?
มันไม่จำเป็นจริงๆแต่ก็ไม่เลวที่จะใช้เช่นกัน
ทำไมคุณทำ
head = std::move(head->next)
ไม่ได้? เป็นเพราะมันจะส่งผลให้หน่วยความจำรั่วหรือเปล่า?
คุณสามารถ. จะไม่มีการรั่วไหลในตัวอย่างนี้
เมื่อ
head
ถูกกำหนดใหม่จะunique_ptr
ทำให้หน่วยความจำปัจจุบันถูกชี้ไปโดยอัตโนมัติหรือไม่?
ใช่. อย่างไรก็ตามตัวชี้เก่าจะไม่ถูกdelete
'd จนกว่าจะโอนความเป็นเจ้าของตัวชี้ใหม่ก่อน ต่อ cppreference:
https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D
เจ้าของรับส่งจาก
r
ไป*this
ราวกับว่าโดยการเรียกreset(r.release())
ตามที่ได้รับมอบหมายของจากget_deleter()
std::forward<E>(r.get_deleter())
https://en.cppreference.com/w/cpp/memory/unique_ptr/reset
แทนที่วัตถุที่มีการจัดการ
ระบุ
current_ptr
ตัวชี้ที่ถูกจัดการโดย*this
ดำเนินการต่อไปนี้ตามลำดับนี้:
- บันทึกสำเนาของตัวชี้ปัจจุบัน
old_ptr = current_ptr
- เขียนทับตัวชี้ปัจจุบันด้วยอาร์กิวเมนต์
current_ptr = ptr
if(old_ptr) get_deleter()(old_ptr)
หากตัวชี้เก่าไม่ว่างเปล่าลบวัตถุที่มีการจัดการก่อนหน้านี้
ดังนั้น:
ในกรณีที่temp
มีการใช้งานตัวชี้ไปยังโหนดเก่าในhead
จะถูกย้ายไปที่temp
ตัวสร้างการย้ายก่อนโดยการรีเซ็ตhead
เพื่อถือ a nullptr
. จากนั้นhead.operator=
จะเรียกnext.release()
และรับตัวชี้นั้น จากนั้นtemp
จะออกนอกขอบเขตdelete
'ในโหนดเก่า
ในกรณีที่temp
ไม่ได้ใช้งานhead.operator=
จะโทรnext.release()
บันทึกตัวชี้เก่าและแทนที่ด้วยตัวชี้ที่ปล่อยแล้วจากนั้นdelete
ตัวชี้ที่บันทึกไว้
ไม่มีการรั่วไหลทั้งสองทาง
ฉันรู้สึกว่าตัวชี้อัจฉริยะเป็นหลักฐานที่โง่เขลาจากการรั่วไหลของหน่วยความจำ
ถ้าใช้ถูกก็ใช่
ดูเหมือนว่าในกรณีนี้อาจมีการรั่วไหลของหน่วยความจำสำหรับต้นฉบับ
head
เนื่องจากจะไม่มีตัวชี้อัจฉริยะชี้ไปที่มันอีกต่อไป?
ไม่มีการรั่วไหลเนื่องจากมีการunique_ptr
อ้างถึงโหนดเก่าอยู่เสมอจนกว่าจะpop()
ออกและtemp
ถูกทำลายdelete
'ติดตั้งโหนดเก่าด้วย แม้ว่าtemp
จะถูกละไว้โหนดเก่าก็ยังคงถูกทำลายอย่างเหมาะสมหลังจากโอนความเป็นเจ้าของnext
ตัวชี้แล้ว