dynamische arrays und kopieren derselben



  • hallo
    Ich habe folgendes problem. Und zwar muss ich einen array (mit anfangsgrösse 2) mit werten auffüllen. sobald der array voll ist, soll ein neuer array erzeugt werden (also mit der grösse 4), die alten werte in den neuen kopiert werden, und der alte dann schliesslich gelöscht werden. Wenn der widerum voll ist, wird ein neuer von der gröss 8 erzeugt, kopiert, der alte gelöscht usw.

    wie muss ich das genau machen mit dem erzeugen der dynamischen arrays, dem kopieren und löschen?

    vielen dank



  • am besten kapselt du den ganzen kram in einer eigenen klasse. in der klasse merkst du dir die aktuelle kapazität des arrays (deine 2, 4 etc.) und die aktuelle größe. wobei die größe bei 0 beginnt und jedesmal, wenn ein item eingefügt wird um eins erhöht wird. sollte die größe die kapazität übersteigen, erzeugst du ein neues array doppelter größe (am einfachsten per new), kopierst das alte array dort hinein (memcpy) und löscht das alte array (delete).



  • hi, danke für die rasche antwort. So halbwegs hab ichs verstanden. Noch was zum dynamischen array: Wenn ich sowas hier mache:

    int g = 2;
    int *stack = new int[g];

    was habe ich nun genau definiert? ein array mit grösse 2?

    und wie geht das genau mit dem kopieren? kann ich nicht einfach array1 = array2; zuweisen?

    gruss



  • jup, damit hast du ein "array" der größe 2 definiert. array deshalb in anführungszeichen, weil stack eigentlich kein array ist. mit "int *stack = new int[g]" reservierst du im speicher aufeinanderfolgenden platz, groß genug, um zwei ints aufzunehmen, wobei stack auf die erste stelle zeigt. umgangssprachlich aber ein array.

    genau das ist aber auch der grund, warum du durch zuweisung nicht das erreichst, was du möchtest. da stack "nur" ein pointer ist, würdest du diesen durch die zuweisung lediglich auf einen anderen speicherbereich umbiegen, der sehr wahrscheinlich einfach uninitialisierten müll enthält.

    deshalb müssen die daten aus dem alten "array" noch in das neue kopiert werden. und dafür gibs die funktion memcpy.



  • du könntest es auch so machen, das du den speicher mit calloc und realloc reservierst.
    du nimmst dein grundarray
    int *a = (int *)calloc(sizeof(int),2);
    und füllst dieses mit werten. sobald du am ende bist, reservierst du entw. ganz neuen speicher, oder erweiterst deinen bestehenden speicher um 2 intgroße speicherstellen.
    a = (int )realloc(a,2sizeof(int));
    dann wieder bis ans ende und erweitern...



  • thordk schrieb:

    jup, damit hast du ein "array" der größe 2 definiert. array deshalb in anführungszeichen, weil stack eigentlich kein array ist. mit "int *stack = new int[g]" reservierst du im speicher aufeinanderfolgenden platz, groß genug, um zwei ints aufzunehmen, wobei stack auf die erste stelle zeigt. umgangssprachlich aber ein array.

    genau das ist aber auch der grund, warum du durch zuweisung nicht das erreichst, was du möchtest. da stack "nur" ein pointer ist, würdest du diesen durch die zuweisung lediglich auf einen anderen speicherbereich umbiegen, der sehr wahrscheinlich einfach uninitialisierten müll enthält.

    deshalb müssen die daten aus dem alten "array" noch in das neue kopiert werden. und dafür gibs die funktion memcpy.

    also wenn ich den array mit einer einfachen "=" und nachher die werte aus dem neuen array abfrage, bekomm ich teilweise die richtigen werte, und teilweise komische sachen zurück.
    Wie muss ich das genau mit memcpy machen? Ansonsten vielen dank für eure antworten, hat mir schon recht weitergeholfen.

    glg





  • langweilig sonntag. hab mal nen beispiel gebastelt.

    class Container
    {
        private:
            int capacity;
            int tsize;
            int *data;
    
            void resize()
            {
                // neuen speicher allozieren
                int *buf = new int[capacity * 2];
                // daten in den neuen speicherbereich kopieren
                memcpy(buf, data, sizeof(int) * capacity);
                // den alten speicher freigeben
                delete[] data;
                // pointer umbiegen
                data = buf;
                // capacity auf neuen wert setzen
                capacity *= 2;
            }
    
        public:
            Container() : capacity(2), tsize(0)
            {
                data = new int[capacity];
            }
    
            ~Container()
            {
                delete[] data;
            }
    
            int size()
            {
                return tsize;
            }
    
            void add(int item)
            {
                if(tsize >= capacity)
                    resize();
                data[tsize++] = item;
            }
    
            int get(int index)
            {
                return data[index];
            }
    };
    


  • template<typename T>
    class dynamic_array
    {
    	std::size_t m_size;
    	T*			m_data;
    
    public:
    	dynamic_array(std::size_t size = 0) : m_size(size), m_data(new T[size]) {}
    	dynamic_array(const T* data, std::size_t size) : m_size(size), m_data(new T[size]) 
    	{ std::copy(data, data + size, m_data); }
    	dynamic_array(dynamic_array const& rhs) : m_size(rhs.m_size), m_data(new T[rhs.m_size])
    	{ std::copy(rhs.m_data, rhs.m_data + m_size, m_data); }
    	dynamic_array& operator=(dynamic_array const& rhs) 
    	{ m_size = rhs.m_size; m_data = new T[m_size]; std::copy(rhs.m_data, rhs.m_data + m_size, m_data); return *this; }
    	~dynamic_array() { delete[] m_data; }
    
    	inline std::size_t size() const { return m_size; }
    	void push_back(T const& data)
    	{
    		resize(m_size + 1);
    		m_data[m_size++] = data;
    	}
    	void resize(std::size_t size) 
    	{
    		T* tmp = new T[size];
    		std::copy(m_data, m_data + std::min<std::size_t>(size, m_size), tmp);
    		delete [] m_data;
    		m_data = tmp;
    	}
    	T const& at(std::size_t index) const 
    	{ if (index >= m_size) throw std::out_of_range("index"); return m_data[index]; }
    	T& at(std::size_t index) 
    	{ if (index >= m_size) throw std::out_of_range("index"); return m_data[index]; }
    };
    

    ach das geht doch schnell 😛 Jetzt einmal so, dass er nur so viel Speicher holt, wie er braucht. Aja und nicht die großen 3 vergessen! 😛

    Nutzen:

    // entweder vorher Größe angeben
    dynamic_array<int> data(2);
    for (std::size_t i = 0; i < data.size(); ++i)
        data.at(i) = i * 10;
    
    // Einfaches Anfügen ...
    data.push_back(30);
    
    // Normalen Array kopieren:
    int static_data[] = { 40, 50, 60, 70, 80 };
    dynamic_array<int> static_to_dynamic_data(static_data, sizeof(static_data));
    

    ... usw ... ^^


Anmelden zum Antworten