แอปทดสอบอย่างง่าย:
cout << new int[0] << endl;
เอาท์พุท:
0x876c0b8
ดังนั้นจึงดูเหมือนว่ามันใช้งานได้ มาตรฐานพูดถึงอะไรเกี่ยวกับเรื่องนี้? เป็นเรื่องถูกกฎหมายหรือไม่ที่จะ "จัดสรร" บล็อกหน่วยความจำที่ว่างเปล่าอยู่เสมอ?
แอปทดสอบอย่างง่าย:
cout << new int[0] << endl;
เอาท์พุท:
0x876c0b8
ดังนั้นจึงดูเหมือนว่ามันใช้งานได้ มาตรฐานพูดถึงอะไรเกี่ยวกับเรื่องนี้? เป็นเรื่องถูกกฎหมายหรือไม่ที่จะ "จัดสรร" บล็อกหน่วยความจำที่ว่างเปล่าอยู่เสมอ?
คำตอบ:
จาก 5.3.4 / 7
เมื่อค่าของนิพจน์ใน direct-new-declarator นั้นเป็นศูนย์ฟังก์ชันการจัดสรรจะถูกเรียกให้จัดสรรอาร์เรย์โดยไม่มีองค์ประกอบ
จาก 3.7.3.1/2
ผลกระทบของการยกเลิกการลงทะเบียนตัวชี้ที่ส่งคืนเนื่องจากการร้องขอขนาดศูนย์ไม่ได้กำหนดไว้
ด้วย
แม้ว่าขนาดของพื้นที่ที่ร้องขอ [โดยใหม่] เป็นศูนย์คำขออาจล้มเหลว
ซึ่งหมายความว่าคุณสามารถทำได้ แต่คุณไม่สามารถถูกต้องตามกฎหมาย (ในลักษณะที่กำหนดไว้อย่างดีในทุกแพลตฟอร์ม) ยกเลิกการจำหน่วยความจำที่คุณได้รับ - คุณสามารถส่งไปยังการลบแถวลำดับและคุณควรลบ
นี่คือบันทึกย่อที่น่าสนใจ (เช่นไม่ใช่ส่วนหนึ่งเชิงมาตรฐานของมาตรฐาน แต่รวมถึงเพื่อวัตถุประสงค์ในการอธิบาย) ที่แนบมากับประโยคจาก 3.7.3.1/2
[32 ความตั้งใจที่จะมีตัวดำเนินการใหม่ () สามารถนำไปใช้ได้โดยการเรียก malloc () หรือ calloc () ดังนั้นกฎจึงเหมือนกันอย่างมีนัยสำคัญ C ++ แตกต่างจาก C ในการขอศูนย์เป็นศูนย์เพื่อส่งกลับตัวชี้ที่ไม่ใช่โมฆะ]
new[]
กับ a delete[]
- ไม่ว่าขนาดใด โดยเฉพาะอย่างยิ่งเมื่อคุณโทรหาnew[i]
คุณจำเป็นต้องมีหน่วยความจำมากกว่าที่คุณพยายามจัดสรรเพื่อจัดเก็บขนาดของอาร์เรย์ (ซึ่งจะถูกใช้ในภายหลังdelete[]
เมื่อทำการจัดสรรคืน)
ใช่มันถูกกฎหมายที่จะจัดสรรอาร์เรย์ขนาดศูนย์แบบนี้ แต่คุณต้องลบมันด้วย
int ar[0];
ผิดกฎหมายทำไมจึงเป็นเรื่องใหม่
sizeof (type)
ว่าคาดว่าจะไม่กลับมาเป็นศูนย์ ดูตัวอย่าง: stackoverflow.com/questions/2632021/can-sizeof-return-0-zero
มาตรฐานพูดถึงอะไรเกี่ยวกับเรื่องนี้? เป็นเรื่องถูกกฎหมายหรือไม่ที่จะ "จัดสรร" บล็อกหน่วยความจำที่ว่างเปล่าอยู่เสมอ?
วัตถุทุกชิ้นมีเอกลักษณ์เฉพาะตัวเช่นที่อยู่เฉพาะซึ่งหมายถึงความยาวที่ไม่เป็นศูนย์ (จำนวนหน่วยความจำจริงจะเพิ่มขึ้นอย่างเงียบ ๆ หากคุณขอศูนย์ไบต์)
หากคุณจัดสรรมากกว่าหนึ่งในวัตถุเหล่านี้คุณจะพบว่าพวกเขามีที่อยู่ที่แตกต่างกัน
operator []
เก็บขนาดของอาเรย์ด้วย (ดูที่isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array ) ดังนั้นหากการดำเนินการจัดสรรจำนวนไบต์กับข้อมูลก็สามารถจัดสรรสำหรับการนับไบต์และ 0 ไบต์สำหรับข้อมูลกลับ 1 ตัวชี้อดีตที่ผ่านมา
operator new[]
ควรกลับไปชี้ที่แตกต่างกัน BTW new expression
มีกฎเพิ่มเติมบางอย่าง (5.3.4) ฉันไม่พบร่องรอยใด ๆ ที่new
มีขนาด 0 จำเป็นต้องจัดสรรอะไรจริงๆ ขออภัยฉันลงคะแนนเพราะฉันพบว่าคำตอบของคุณไม่ได้ตอบคำถาม แต่ให้ข้อโต้แย้งบางอย่าง
new[]
การนำไปใช้เพื่อส่งคืนที่อยู่ในช่วงที่ไม่มีการแมปหน่วยความจำแบบไดนามิกดังนั้นจึงไม่ได้ใช้หน่วยความจำใด ๆ จริงๆ (ในขณะที่ใช้พื้นที่ที่อยู่)
while(!exitRequested) { char *p = new char[0]; delete [] p; }
วนรอบโดยไม่มีการรีไซเคิลตัวชี้จะยุบตัวเป็นฝุ่นก่อนที่มันจะหมดพื้นที่ที่อยู่ แต่บนแพลตฟอร์มที่มีตัวชี้ 32 บิตที่จะ สมมติฐานที่สมเหตุสมผลน้อยกว่ามาก
ใช่มันเป็นกฎหมายอย่างสมบูรณ์จะจัดสรรบล็อกขนาด0
new
คุณไม่สามารถทำอะไรที่เป็นประโยชน์กับมันได้เนื่องจากไม่มีข้อมูลที่ถูกต้องให้คุณเข้าถึง int[0] = 5;
ผิดกฎหมาย
อย่างไรก็ตามฉันเชื่อว่ามาตรฐานอนุญาตให้สิ่งต่าง ๆmalloc(0)
กลับมาNULL
อีก
คุณจะต้องdelete []
ชี้ไปที่สิ่งที่คุณได้รับจากการจัดสรรเช่นกัน
อยากรู้อยากเห็น C ++ ต้องการตัวดำเนินการใหม่ส่งกลับตัวชี้ที่ถูกต้องแม้ว่าจะมีการร้องขอศูนย์ไบต์ (การขอให้มีพฤติกรรมที่ทำให้เกิดเสียงแปลก ๆ ทำให้สิ่งต่าง ๆ ในภาษาง่ายขึ้น)
ฉันพบว่ามีผลบังคับใช้ C ++ Third Editionกล่าวเช่นนี้ใน "รายการ 51: ปฏิบัติตามข้อตกลงเมื่อเขียนใหม่และลบ"
ฉันรับประกันว่า int ใหม่ [0] จะทำให้คุณมีพื้นที่เพิ่มขึ้นเนื่องจากฉันได้ทำการทดสอบแล้ว
ตัวอย่างเช่นการใช้หน่วยความจำของ
int **arr = new int*[1000000000];
มีขนาดเล็กกว่าอย่างมีนัยสำคัญ
int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
arr[i]=new int[0];
}
การใช้หน่วยความจำของข้อมูลโค้ดที่สองลบด้วยโค้ดตัวอย่างแรกคือหน่วยความจำที่ใช้สำหรับ int ใหม่จำนวนมาก [0]