จัดสรรหน่วยความจำเพิ่มเติมสำหรับอาร์เรย์ที่จัดสรรแบบไดนามิก

อัลกอริธึม C++ ของฉันได้รับข้อมูลที่ไม่ทราบขนาด (ตรวจพบอนุภาคบนภาพทีละภาพ และฉันไม่รู้ว่าจะมีการตรวจพบอนุภาคจำนวนเท่าใดก่อนที่อัลกอริธึมนี้จะทำงานเสร็จ) ก่อนอื่นฉันต้องการจัดสรรเช่นอาร์เรย์ที่มีองค์ประกอบ 10,000 รายการและในระหว่างการประมวลผลหากจำเป็นให้จัดสรรองค์ประกอบอีก 10,000 รายการหลายครั้ง

นี่คือสิ่งที่ฉันลอง มันใช้งานไม่ได้:

#include <iostream>
using namespace std;
int main(){
    int n = 3;
    int m = 3;
    float *a = new float[3];
    a[0] = 0;
    a[1] = 1;
    a[2] = 2;
    float *b = a + 2;
    b = new float[3];
    b[0] = 4;
    b[1] = 5;
    cout << a[3] << endl;
} 

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

แต่ยังมีวิธีที่จะเพิ่มขนาดของวิธีการจัดสรรแบบไดนามิกของคุณหรือไม่? สิ่งที่ฉันต้องการในตัวอย่างของเล่นคือการเพิ่มจำนวนองค์ประกอบในอาร์เรย์ a ขึ้น 3 ดังนั้นมันจึงจะมีองค์ประกอบ 6

ใน Matlab เป็นไปได้อย่างแน่นอน แล้ว C++ ล่ะ?

ขอบคุณ


person Mikhail Genkin    schedule 12.03.2015    source แหล่งที่มา
comment
คุณต้องมีอาร์เรย์แบบไดนามิก C++ ให้คุณ std::vector เพื่อจุดประสงค์นั้น - คุณไม่จำเป็นต้องกังวลเกี่ยวกับการจัดสรรหน่วยความจำ   -  person Charles Salvia    schedule 12.03.2015


คำตอบ (3)


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

โชคดีที่ไลบรารีมาตรฐานมีคอนเทนเนอร์ที่จะจัดการสิ่งนี้โดยอัตโนมัติ รวมถึง vector ซึ่งเป็นอาร์เรย์ที่ปรับขนาดได้

std::vector<float> a(3);
a[0] = 0;
a[1] = 1;
a[2] = 2;

// you can resize it by specifying a new size
a.resize(4);
a[3] = 3;

// or by appending new elements
a.push_back(4);
person Mike Seymour    schedule 12.03.2015
comment
ขอบคุณ! ใช่แล้ว ดูเหมือนว่าคลาสเวกเตอร์จะเป็นวิธีแก้ปัญหาที่ง่ายที่สุด - person Mikhail Genkin; 12.03.2015

คุณควรใช้ std::vector แทนอาร์เรย์ดิบ นำไปปฏิบัติให้เติบโตอย่างมีประสิทธิภาพ คุณสามารถเปลี่ยนขนาดได้ด้วย resize ต่อท้ายด้วย push_back หรือแทรกช่วง (หรือสิ่งอื่นๆ มากมาย) ด้วย insert เพื่อขยาย

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

person Baum mit Augen    schedule 12.03.2015

คุณควรใช้ vector และ resize เมื่อจำเป็น หรือปล่อยให้ขยายเอง

เมื่อคุณทำ:

float *b = a + 2;
b = new float[3];

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

person Eric Fortin    schedule 12.03.2015