C++ การจัดสรรอาร์เรย์แบบไดนามิกพร้อมตัวอย่าง

⚡ สรุปอย่างชาญฉลาด

C++ การจัดสรรอาร์เรย์แบบไดนามิก อธิบายวิธีการจัดสรร ปรับขนาด และลบอาร์เรย์บนฮีปในระหว่างการทำงานของโปรแกรม Lessons ครอบคลุมรูปแบบหน่วยความจำใหม่ ลบ การเริ่มต้น การคัดลอก การปรับขนาด และความปลอดภัย

  • 🧠 การจัดสรรฮีป: คำสั่ง `new int[size]` สร้างอาร์เรย์ที่มีขนาดที่ทราบได้ในขณะรันไทม์
  • 🔁 การเริ่มต้น: new int[size](){} กำหนดค่าศูนย์ให้กับหน่วยความจำ วงเล็บปีกกาจะกำหนดค่าคงที่
  • 📏 การปรับขนาด: จัดสรรพื้นที่จัดเก็บข้อมูลให้ใหญ่ขึ้น คัดลอกโดยใช้ std::copy จากนั้นลบบัฟเฟอร์เก่าทิ้ง
  • 🧹 ลบอย่างถูกวิธี: ควรใช้เมธอด delete[] กับอาร์เรย์เสมอ ห้ามใช้เมธอด delete ธรรมดา
  • 📦 ควรใช้ std::vector: ทันสมัย C++ รองรับเวกเตอร์สำหรับการปรับขนาดอัตโนมัติและ RAII
  • 🤖 AI Revเอียว: ผู้ช่วย AI ตรวจจับการรั่วไหลและแนะนำคำแนะนำที่ชาญฉลาด

C++ การจัดสรรอาร์เรย์แบบไดนามิก

ไดนามิกอาร์เรย์คืออะไร?

อาร์เรย์แบบไดนามิกค่อนข้างคล้ายกับอาร์เรย์ทั่วไป แต่ขนาดของอาร์เรย์สามารถแก้ไขได้ในระหว่างรันไทม์ของโปรแกรม องค์ประกอบ DynamArray ครอบครองบล็อกหน่วยความจำที่อยู่ติดกัน

เมื่อสร้างอาร์เรย์แล้ว จะไม่สามารถเปลี่ยนแปลงขนาดได้ อย่างไรก็ตาม อาร์เรย์แบบไดนามิกจะแตกต่างออกไป อาร์เรย์แบบไดนามิกสามารถขยายขนาดได้แม้ว่าจะเต็มแล้วก็ตาม

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

ปัจจัยที่ส่งผลต่อประสิทธิภาพของอาร์เรย์ไดนามิก

ขนาดเริ่มต้นของอาร์เรย์และปัจจัยการเติบโตจะกำหนดประสิทธิภาพการทำงาน โปรดสังเกตจุดต่อไปนี้:

  1. หากอาร์เรย์มีขนาดเล็กและมีปัจจัยการเติบโตเล็กน้อย อาเรย์ก็จะทำการจัดสรรหน่วยความจำใหม่บ่อยขึ้น สิ่งนี้จะลดประสิทธิภาพของอาเรย์
  2. หากอาร์เรย์มีขนาดใหญ่และมีปัจจัยการเติบโตสูง ก็จะมีหน่วยความจำที่ไม่ได้ใช้งานจำนวนมาก เนื่องด้วยเหตุนี้ การดำเนินการปรับขนาดอาจใช้เวลานานขึ้น ซึ่งจะลดประสิทธิภาพของอาร์เรย์

คำหลักใหม่

In C++เราสามารถสร้างอาร์เรย์แบบไดนามิกโดยใช้คีย์เวิร์ด new จำนวนรายการที่ต้องจัดสรรจะระบุไว้ในวงเล็บเหลี่ยมคู่หนึ่ง ชื่อประเภทควรอยู่ข้างหน้านี้ จำนวนรายการที่ต้องการจะได้รับการจัดสรร

วากยสัมพันธ์

คำหลักใหม่ใช้รูปแบบต่อไปนี้:

pointer_variable = new data_type;

pointer_variable คือชื่อของ ตัวแปรตัวชี้.

data_type จะต้องถูกต้อง C++ ประเภทข้อมูล.

คำหลักจะส่งกลับตัวชี้ไปยังรายการแรก หลังจากสร้างอาร์เรย์แบบไดนามิกแล้ว เราสามารถลบออกได้โดยใช้คีย์เวิร์ด Delete

1 ตัวอย่าง:

#include<iostream>
using namespace std;
int main() {
	int x, n;
	cout << "Enter the number of items:" << "\n";
	cin >>n;
	int *arr = new int[n];
	cout << "Enter " << n << " items" << endl;
	for (x = 0; x < n; x++) {
		cin >> arr[x];
	}
	cout << "You entered: ";
	for (x = 0; x < n; x++) {
		cout << arr[x] << " ";
	}
	return 0;
}

Output:

คำหลักใหม่

นี่คือภาพหน้าจอของรหัส:

คำหลักใหม่

Code คำอธิบาย:

  1. รวมไฟล์ส่วนหัว iostream ลงในโปรแกรมของเราเพื่อใช้งาน ฟังก์ชั่น.
  2. รวมเนมสเปซมาตรฐานไว้ในโปรแกรมของเราเพื่อใช้คลาสโดยไม่ต้องเรียกมัน
  3. เรียกใช้ฟังก์ชัน main() ควรเพิ่มตรรกะของโปรแกรมภายในเนื้อหาของฟังก์ชัน
  4. ประกาศตัวแปรจำนวนเต็มสองตัว x และ n
  5. พิมพ์ข้อความบนคอนโซลเพื่อให้ผู้ใช้ป้อนค่าของตัวแปร n
  6. อ่านอินพุตของผู้ใช้จากคีย์บอร์ดและกำหนดให้กับตัวแปร n
  7. ประกาศอาร์เรย์เพื่อเก็บจำนวนเต็ม n จำนวนและกำหนดให้กับตัวแปรตัวชี้ *arr
  8. พิมพ์ข้อความแจ้งให้ผู้ใช้ป้อนจำนวน n รายการ
  9. ใช้ for loop เพื่อสร้างตัวแปร loop x เพื่อวนซ้ำรายการที่ผู้ใช้ป้อน
  10. อ่านองค์ประกอบที่ผู้ใช้ป้อนและจัดเก็บไว้ในอาร์เรย์ arr
  11. ส่วนปลายของลำตัว สำหรับห่วง.
  12. พิมพ์ข้อความบนคอนโซล
  13. ใช้ for loop เพื่อสร้างตัวแปร loop x เพื่อวนซ้ำรายการของอาร์เรย์
  14. พิมพ์ค่าที่มีอยู่ในอาร์เรย์ชื่อ arr บนคอนโซล
  15. ส่วนท้ายของ for loop
  16. โปรแกรมจะต้องคืนค่าเมื่อเสร็จสิ้นสำเร็จ
  17. ส่วนท้ายของฟังก์ชัน main()

หมายเหตุ: ในตัวอย่างข้างต้น ผู้ใช้จะได้รับอนุญาตให้ระบุขนาดใดก็ได้สำหรับอาร์เรย์ในระหว่างรันไทม์ ซึ่งหมายความว่าขนาดของอาร์เรย์จะถูกกำหนดระหว่างรันไทม์.

การเริ่มต้นอาร์เรย์ที่จัดสรรแบบไดนามิก

ง่ายต่อการเริ่มต้นอาร์เรย์แบบไดนามิกเป็น 0

ไวยากรณ์:

int *array{ new int[length]{} };

ในรูปแบบข้างต้น ความยาวหมายถึงจำนวนองค์ประกอบที่จะเพิ่มในอาร์เรย์ เนื่องจากเราต้องกำหนดค่าเริ่มต้นให้กับอาร์เรย์เป็น 0 จึงควรเว้นว่างไว้

เราสามารถเริ่มต้นอาร์เรย์แบบไดนามิกได้โดยใช้รายการเริ่มต้น เรามาสร้างตัวอย่างที่แสดงให้เห็นสิ่งนี้กัน

2 ตัวอย่าง:

#include <iostream>
using namespace std;

int main(void) {

	int x; 

	int *array{ new int[5]{ 10, 7, 15, 3, 11 } };

	cout << "Array elements: " << endl;

	for (x = 0; x < 5; x++) {

		cout << array[x] << endl;
	}

	return 0;
}

Output:

การเริ่มต้นอาร์เรย์ที่จัดสรรแบบไดนามิก

นี่คือภาพหน้าจอของรหัส:

การเริ่มต้นอาร์เรย์ที่จัดสรรแบบไดนามิก

Code คำอธิบาย:

  1. รวมไฟล์ส่วนหัว iostream ลงในโปรแกรมของเราเพื่อใช้ฟังก์ชันต่างๆ
  2. รวมเนมสเปซมาตรฐานในโปรแกรมของเราเพื่อใช้คลาสโดยไม่ต้องเรียกมัน
  3. เรียกใช้ฟังก์ชัน main() ควรเพิ่มตรรกะของโปรแกรมภายในเนื้อหาของฟังก์ชัน
  4. ประกาศตัวแปรจำนวนเต็มชื่อ x
  5. ประกาศอาร์เรย์แบบไดนามิกชื่ออาร์เรย์โดยใช้รายการตัวเริ่มต้น อาร์เรย์จะเก็บองค์ประกอบจำนวนเต็ม 5 รายการ โปรดทราบว่าเราไม่ได้ใช้ตัวดำเนินการ “=” ระหว่างความยาวของอาร์เรย์และรายการตัวเริ่มต้น
  6. พิมพ์ข้อความบนคอนโซล จุดสิ้นสุดคือ a C++ คำสำคัญที่หมายถึงบรรทัดสิ้นสุด มันเลื่อนเคอร์เซอร์ไปที่ประโยคถัดไป
  7. ใช้ for loop เพื่อวนซ้ำองค์ประกอบอาร์เรย์
  8. พิมพ์เนื้อหาของอาร์เรย์ชื่ออาร์เรย์บนคอนโซล
  9. ส่วนท้ายของ for loop
  10. โปรแกรมจะต้องคืนค่าเมื่อเสร็จสิ้นสำเร็จ
  11. ส่วนท้ายของฟังก์ชัน main()

การปรับขนาดอาร์เรย์

ความยาวของอาร์เรย์แบบไดนามิกถูกตั้งค่าในช่วงเวลาการจัดสรร

อย่างไรก็ตาม C++ ไม่มีกลไกในการปรับขนาดอาร์เรย์ในตัวเมื่อได้รับการจัดสรรแล้ว

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

หมายเหตุ: เทคนิคนี้มีแนวโน้มที่จะเกิดข้อผิดพลาด ดังนั้นควรพยายามหลีกเลี่ยง

การลบอาร์เรย์แบบไดนามิก

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

หมายเหตุ

หากต้องการลบอาร์เรย์แบบไดนามิกออกจากหน่วยความจำคอมพิวเตอร์ คุณควรใช้ Delete[] แทนการลบ [] สั่งให้ CPU ลบตัวแปรหลายตัวแทนที่จะลบตัวแปรเดียว การใช้การลบแทนการลบ[]เมื่อจัดการกับอาร์เรย์แบบไดนามิกอาจทำให้เกิดปัญหาได้ ตัวอย่างของปัญหาดังกล่าว ได้แก่ หน่วยความจำรั่ว ข้อมูลเสียหาย ล่ม ฯลฯ

3 ตัวอย่าง:

#include<iostream>
using namespace std;
int main() {
	int x, n;
	cout << "How many numbers will you type?" << "\n";
	cin >>n;
	int *arr = new int[n];
	cout << "Enter " << n << " numbers" << endl;
	for (x = 0; x < n; x++) {
		cin >> arr[x];
	}
	cout << "You typed: ";
	for (x = 0; x < n; x++) {
		cout << arr[x] << " ";
	}
	cout << endl;
	delete [] arr;
	return 0;
}

Output:

การลบอาร์เรย์แบบไดนามิก

นี่คือภาพหน้าจอของรหัส:

การลบอาร์เรย์แบบไดนามิก

Code คำอธิบาย:

  1. รวมไฟล์ส่วนหัว iostream ไว้ในโปรแกรมของเราเพื่อใช้ฟังก์ชันต่างๆ
  2. รวมเนมสเปซมาตรฐานไว้ในโปรแกรมของเราเพื่อใช้คลาสโดยไม่ต้องเรียกมัน
  3. เรียกใช้ฟังก์ชัน main() ควรเพิ่มตรรกะของโปรแกรมภายในเนื้อหาของฟังก์ชัน
  4. ประกาศตัวแปรสองตัว x และ n ของชนิดข้อมูลจำนวนเต็ม
  5. พิมพ์ข้อความบนคอนโซล ข้อความจะขอให้ผู้ใช้ระบุจำนวนตัวเลขที่จะป้อน
  6. อ่านอินพุตของผู้ใช้จากแป้นพิมพ์ ค่าอินพุตจะถูกกำหนดให้กับตัวแปร n
  7. ประกาศตัวแปรพอยน์เตอร์ *arr อาร์เรย์ arr จะสำรองหน่วยความจำบางส่วนเพื่อจัดเก็บจำนวนเต็ม n จำนวน
  8. พิมพ์ข้อความบนคอนโซลเพื่อแจ้งให้ผู้ใช้ป้อนตัวเลข n ตัว
  9. สร้างลูป for และตัวแปรลูป x เพื่อวนซ้ำตามตัวเลขที่ผู้ใช้ป้อน
  10. อ่านตัวเลขที่ผู้ใช้ป้อนและจัดเก็บไว้ในอาร์เรย์ arr
  11. ส่วนท้ายของ for loop
  12. พิมพ์ข้อความบนคอนโซล
  13. ใช้ตัวแปร for loop และตัวแปร x เพื่อวนซ้ำเนื้อหาของอาร์เรย์ arr
  14. พิมพ์ค่าของอาร์เรย์ arr บนคอนโซล
  15. ส่วนท้ายของ for loop
  16. พิมพ์บรรทัดว่างบนคอนโซล
  17. เพิ่มหน่วยความจำของอาร์เรย์ arr
  18. โปรแกรมจะคืนค่าเมื่อดำเนินการสำเร็จ
  19. ส่วนท้ายของฟังก์ชัน main()

คำถามที่พบบ่อย

ขนาดของอาร์เรย์แบบคงที่ (Static arrays) จะถูกกำหนดในระหว่างการคอมไพล์ โดยจัดเก็บไว้บนสแต็ก (stack) ส่วนขนาดของอาร์เรย์แบบไดนามิก (Dynamic arrays) จะถูกกำหนดในระหว่างการทำงาน โดยจัดเก็บไว้บนฮีป (heap)

เครื่องมือ AI ตรวจจับการรั่วไหล ลบ[] ที่หายไป และแนะนำการแทนที่ด้วย unique_ptr หรือ vector

ใช่แล้ว Copilot จะแปลงคำสั่ง new และ delete ดิบๆ ให้เป็น std::vector หรือ smart pointers

จัดสรรพื้นที่ให้ใหญ่ขึ้น คัดลอกด้วย std::copy ลบบัฟเฟอร์เก่า หรือใช้ std::vector

delete[] จะเรียกใช้ destructor และปล่อยบล็อก การใช้ delete กับอาร์เรย์โดยตรงเป็นพฤติกรรมที่ไม่แน่นอน

ใช้เป็นค่าเริ่มต้น มันจัดการหน่วยความจำ รองรับการปรับขนาด ลูปช่วง และข้อยกเว้นได้อย่างปลอดภัย

ลำดับ Syncซิงโครไนซ์การจัดสรร การเข้าถึง และการลบด้วยมิวเท็กซ์หรืออะตอมิกส์

ใช้ std::vector หรือ std::unique_ptr เพื่อหลีกเลี่ยงการลบด้วยตนเอง[]

สรุปโพสต์นี้ด้วย: