Foo* set = new Foo[100];
// ...
delete [] set;
delete[]
คุณไม่ผ่านขอบเขตของอาร์เรย์ไป แต่ข้อมูลนั้นถูกเก็บไว้ที่ไหน? เป็นมาตรฐานหรือไม่
Foo* set = new Foo[100];
// ...
delete [] set;
delete[]
คุณไม่ผ่านขอบเขตของอาร์เรย์ไป แต่ข้อมูลนั้นถูกเก็บไว้ที่ไหน? เป็นมาตรฐานหรือไม่
คำตอบ:
เมื่อคุณจัดสรรหน่วยความจำบนฮีปตัวจัดสรรของคุณจะติดตามจำนวนหน่วยความจำที่คุณจัดสรร โดยปกติจะถูกเก็บไว้ในส่วน "หัว" ก่อนหน่วยความจำที่คุณได้รับการจัดสรร ด้วยวิธีนี้เมื่อถึงเวลาที่จะเพิ่มหน่วยความจำตัวยกเลิกการจัดสรรจะรู้จำนวนหน่วยความจำที่ว่าง
free
รู้ว่าหน่วยความจำมากเพื่อ deallocate" ใช่ขนาดบล็อกหน่วยความจำถูกเก็บไว้ "ที่ใดที่หนึ่ง" โดยmalloc
(ปกติอยู่ในบล็อกของตัวเอง) ดังนั้นนั่นคือวิธีที่จะfree
รู้ อย่างไรก็ตามnew[]
/ delete[]
เป็นเรื่องราวที่แตกต่าง การทำงานหลังพื้นด้านบนของ/malloc
ยังเก็บจำนวนองค์ประกอบที่สร้างขึ้นในบล็อกหน่วยความจำ (เป็นอิสระจาก) เพื่อให้สามารถดึงและใช้หมายเลขนั้นในภายหลังเพื่อเรียกจำนวน destructors ที่เหมาะสม free
new[]
malloc
delete[]
malloc
) และจำนวนองค์ประกอบ (โดยnew[]
) โปรดทราบว่าอดีตไม่สามารถใช้ในการคำนวณหลังได้เนื่องจากในกรณีทั่วไปขนาดของบล็อกหน่วยความจำอาจมีขนาดใหญ่กว่าที่จำเป็นสำหรับอาร์เรย์ขนาดที่ร้องขอจริงๆ นอกจากนี้โปรดทราบว่าตัวนับองค์ประกอบอาเรย์จำเป็นสำหรับประเภทที่มีตัวทำลายที่ไม่สำคัญเท่านั้น สำหรับประเภท destructor เล็กน้อยเคาน์เตอร์ไม่ได้เก็บไว้โดยและแน่นอนไม่ดึงข้อมูลโดยnew[]
delete[]
หนึ่งในแนวทางสำหรับคอมไพเลอร์คือการจัดสรรหน่วยความจำเพิ่มอีกเล็กน้อยและเพื่อเก็บจำนวนองค์ประกอบในองค์ประกอบส่วนหัว
ตัวอย่างวิธีการทำ:
ที่นี่
int* i = new int[4];
คอมไพเลอร์จะจัดสรรsizeof(int)*5
ไบต์
int *temp = malloc(sizeof(int)*5)
จะเก็บ "4" ในsizeof(int)
ไบต์แรก
*temp = 4;
และตั้ง i
i = temp + 1;
ดังนั้นi
จะชี้ไปที่อาร์เรย์ขององค์ประกอบ 4 ไม่ใช่ 5
และการลบ
delete[] i;
จะถูกประมวลผลด้วยวิธีต่อไปนี้:
int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed
free (temp)
ข้อมูลไม่ได้มาตรฐาน อย่างไรก็ตามในแพลตฟอร์มที่ฉันทำงานกับข้อมูลนี้จะถูกเก็บไว้ในหน่วยความจำก่อนองค์ประกอบแรก ดังนั้นคุณสามารถเข้าถึงมันในทางทฤษฎีและตรวจสอบได้อย่างไรก็ตามมันไม่คุ้มค่า
นี่คือสาเหตุที่คุณต้องใช้การลบ [] เมื่อคุณจัดสรรหน่วยความจำด้วย [] ใหม่เนื่องจากการลบรุ่นอาเรย์รู้ว่า (และที่) จะต้องมองหาจำนวนหน่วยความจำที่เหมาะสม - และเรียกจำนวน destructors ที่เหมาะสม สำหรับวัตถุ
โดยทั่วไปจะจัดเรียงในหน่วยความจำเป็น:
[info] [mem ที่คุณขอ ... ]
โดยที่ info เป็นโครงสร้างที่คอมไพเลอร์ใช้ในการจัดเก็บจำนวนหน่วยความจำที่จัดสรรและสิ่งที่ไม่
นี่คือการใช้งานขึ้นอยู่กับว่า
นี่ไม่ใช่สิ่งที่อยู่ในข้อมูลจำเพาะ - มันขึ้นอยู่กับการใช้งาน
มันถูกกำหนดในมาตรฐาน C ++ เพื่อให้คอมไพเลอร์เฉพาะ แปลว่าเวทมนตร์แปล สามารถหยุดได้ด้วยข้อ จำกัด การจัดแนวที่ไม่สำคัญบนแพลตฟอร์มหลักอย่างน้อยหนึ่งแห่ง
คุณสามารถคิดเกี่ยวกับการใช้งานไปได้โดยไม่รู้ว่าdelete[]
ถูกกำหนดไว้เฉพาะสำหรับตัวชี้กลับโดยที่ไม่อาจจะเป็นตัวชี้เช่นเดียวกับการส่งกลับโดยnew[]
operator new[]
การนำไปใช้งานอย่างหนึ่งใน wild คือการเก็บจำนวนอาร์เรย์ใน int แรกที่ส่งคืนโดยoperator new[]
และnew[]
คืนค่าตัวชี้ที่ผ่านมานั้น (นี่คือเหตุผลที่การจัดแนวที่ไม่สำคัญสามารถทำลายnew[]
ได้)
โปรดจำไว้ว่าoperator new[]/operator delete[]
! new[]/delete[]
=
พลัสนี้เป็นมุมฉากกับวิธี C malloc
รู้ขนาดของหน่วยความจำที่จัดสรรโดย
เนื่องจากอาร์เรย์ที่จะ 'ลบ' ควรถูกสร้างขึ้นด้วยการใช้ตัวดำเนินการ 'ใหม่' เพียงครั้งเดียว การดำเนินการ 'ใหม่' ควรใส่ข้อมูลนั้นไว้ในกอง มิฉะนั้นการใช้ประโยชน์เพิ่มเติมของผู้รู้ใหม่จะรู้ได้อย่างไรว่ากองนั้นจบลงอย่างไร
มันไม่ได้มาตรฐาน ในรันไทม์ของ Microsoft ตัวดำเนินการใหม่ใช้ malloc () และตัวดำเนินการลบใช้ฟรี () ดังนั้นในการตั้งค่านี้คำถามของคุณจะเทียบเท่ากับสิ่งต่อไปนี้: ฟรี () รู้ขนาดของบล็อกได้อย่างไร
มีการบันทึกบัญชีเกิดขึ้นเบื้องหลังคือใน C runtime
นี่เป็นปัญหาที่น่าสนใจมากกว่าที่คุณคิดในตอนแรก การตอบกลับนี้เกี่ยวกับการใช้งานที่เป็นไปได้หนึ่งอย่าง
ประการแรกในขณะที่ในบางระดับระบบของคุณจะต้องรู้วิธีการ 'บล็อกฟรี' บล็อกหน่วยความจำ malloc พื้นฐาน / ฟรี (ซึ่งใหม่ / ลบ / ใหม่ [] / ลบ [] โดยทั่วไปโทร) ไม่จำเสมอว่าหน่วยความจำเท่าไหร่ คุณถามว่ามันจะถูกปัดเศษขึ้น (ตัวอย่างเช่นเมื่อคุณอยู่เหนือ 4K มันจะถูกปัดเศษขึ้นเป็นบล็อกขนาด 4K ถัดไป)
ดังนั้นแม้ว่าจะได้ขนาดบล็อกหน่วยความจำ แต่ก็ไม่ได้บอกเราว่ามีค่าเท่าใดในหน่วยความจำ ed [ใหม่] เนื่องจากอาจมีขนาดเล็กลง ดังนั้นเราต้องเก็บจำนวนเต็มพิเศษเพื่อบอกเราว่ามีกี่ค่า
ยกเว้นหากประเภทที่สร้างขึ้นไม่มีตัวทำลายดังนั้นให้ลบ [] โดยไม่ต้องทำอะไรเลยยกเว้นการเพิ่มบล็อกหน่วยความจำและทำให้ไม่ต้องเก็บอะไร!