dynamische arrays nochmal



  • ich meine wie sollen die aufgebaut werden?

    im buch: "c++ lernen und professionell anwenden" gibt es einmal diese Cell
    wo in jedem Objekt ein Zeiger auf das nächste Objekt zeigt und so eine kette entsteht. wird ein objekt dazwischen zerstört, wird der zeiger umgebogen auf das nächstliegende objekt gezeigt. und falls dahinter nichts mehr ist, dann wird es auf NULL gezeigt

    dann lese ich am schluß im Buch dass es noch diese containers gibt
    z.b. Lists, Vector aus STL

    funktioniert das im Prinzip dasselbe wie mit Cell

    dann gibt es noch

    if (numtriangles >= maxtriangles) {
    	TRIANGLE	*tmp = new TRIANGLE [maxtriangles + 1];
    	memcpy (tmp, triangle, maxtriangles * sizeof(TRIANGLE)); 
    	delete[] triangle;
    	triangle = tmp;
    	maxtriangles++;
    }
    

    aber da wird ja immer ein ganzes array kopiert und das alte gelöscht, das kostet performance oder?

    helf mir bitte, ich brauche den besten plattformunabhängigen code für dynamische arrays.

    bei mir geht es darum dass ich zur laufzeit beliebig viele objekte erzeugen kann. die reihenfolge der objekte auch hin und her schieben und zerstören kann. ähnlich wie die layers von Photoshop oder ObjektManager von Cinema4D



  • der satz "funktioniert das im Prinzip dasselbe wie mit Cell " sollte eine frage sein



  • Wenn du wirklich Arrays nutzen willst, und auch Zeigerarithmetik anwenden willst, müssen die Objekte hintereinander im Speicher liegen, und du wirst um das rumkopieren nicht herum kommen.

    Natürlich könntest du so Sachen wie realloc etc. verwenden, aber die haben meiner Meinung nach in C++ nichts zu suchen.

    std::vector und andere Container auch bieten dir auch eine Funktion reserve(std::size_t) an, mit der du den Container im vornherein an eine bestimmte Größe vergrößern kannst.

    Wenn du viele Objekte verschiebst, oft neue hinzukommen usw. könnte eine std::list nützlich sein, da dort einfach ein Zeiger auf das vorherige und das nächste Element gespeichert wird.

    Ok, ich hoffe jetzt ich konnte dir helfen, obwohl ich nicht so recht verstanden habe was du eigentlich möchtest.



  • Wenn du statt new malloc() verwendest, kannst Du das Array auch vergrößern, per realloc(). Ich weiss jetzt nicht, inwiefern es dafüre in C++-Pendant gibt, weil ich das noch nie gebraucht habe.

    Der Code hier ist aus meinem Source-Archiv, ich hab sowas mal gebastelt, hat auch halbwegs gut funktioniert glaub ich :P, können aber Fehler drin sein, ich weiss nicht mehr wie alt der Code ist.... ich heb sowas nur auf falls ichs doch mal wieder brauch :D.
    Aber hier verwende ich realloc. Nimms als Muster ohne Wert, keinesfalls als funktionierenden Code! War glaub ich mal ne Übung aus nem Buch oder so!

    /************************************************
     *   FILE    : dtDynArray.h
     *   Purpose : Dynamic Array Template Class
     *   Author  : (C) D. Gentner
     *   License : Public Domain
     ************************************************/
    
    /** @brief This is an template class which basically presents a dynamic Array.
      */
    template <typename Type>class dtFastArray
    {
    public:
        /** @brief Constructor */
        inline dtFastArray()
        {
            m_storage = NULL;
            m_index   = 0;
            m_current = 5;
            m_storage = (Type*)malloc(sizeof(Type*)*m_current);
        }
    
        /** @brief Deconstructor */
        inline ~dtFastArray()
        {
           Reset();
        }
    
        /** @brief Inits the Class 
          * 
          * Call this function only after you called dtFastArray::Reset().      
          */
        inline bool InitArray()
        {
            m_index   = 0;
            m_current = 5;
            m_storage = (Type*)malloc( sizeof(Type*)*m_current);
            if (m_storage != NULL)
                return true;
            else
                return false;
        }      
    
        /** @brief Adds an Entry 
          * @param data A Pointer to the data you'd like to add.
          * @return The m_index of the Entry.
          */
        inline UINT Add( Type *data)
        {
            if ( m_current <= m_index )
            {
                //Need more space
                m_current += 5;
                m_storage = (Type*)realloc((Type*)m_storage,
                                         (sizeof(Type)*m_current));
                if (!m_storage){
                    return 0;
                }
            }
    
            // Memory should exist, copy
            assert(m_storage);
            memcpy(&m_storage[m_index], data, sizeof(Type));
            m_index++;
    
            // All Good
            return m_index;
        }
    
        /** @brief Returns a specific Member 
          * @param index The index of the Entry you want
          * @return A pointer to the data associated with the index.
          */
        inline Type* Get( const UINT index )
        {
            if (m_storage[index])
                return &m_storage[index];
            else
                return NULL;
        }
    
        /** @brief Searches for Data 
          * @param data The data to search
          * @return the index of the searched item, or -1 if not found.
          */
        inline int FindEntry(const Type* data )
        {
            // NULL is not allowed
            if (!data){            
                return -1;
            }
    
            for ( int i = 0; i < m_index; i++ )
            {
                if (memcmp( &m_storage[i], &data, sizeof(Type*)) == 0)
                    return i;
            }
    
            return -1;
        }
    
        /** @brief Deletes a member.
          * @param ID The index of the Member to delete
          * @return Returns the new highest m_index or -1 if not found.
          */
        inline int Delete ( int ID )
        {
            if ( ID < 0 ) { return -1; }
    
            memmove( &m_storage[ID] , &m_storage[m_index - 1], sizeof(Type*) );
            return m_index--;
        }
    
        /** @brief Returns the Highest m_index
          * @return The highest m_index.
          */
        inline int UBound(){ return m_index; }
    
        /** @brief Resets Class and removes everything */
        inline void Reset()
        {
            for (int i = 0; i < UBound(); i++)
            {
                Delete(i);
            }
            dtDelete(m_storage);
            m_index = m_current = 0;
            ZeroMemory( this, sizeof(dtFastArray) );
        }
    
        /** @brief Overloaded operator[].
          * @param m_index The index requested.
          * @return The data.
          *
          * With this construct you may access an Instance like a normal array.<br>
          * Sample:<br>
          * @code
          * dtFastArray<int> array;
          * printf("Member 0 has Value: %i", array[0]");
          * @endcode
          * Dead simple. ;)
          */
        inline Type operator[]( int m_index)
        {
            if (m_storage[m_index])
                return m_storage[m_index]; 
            else
              throw std::runtime_error("dtFastArray::operator[]: Index out of Bounds");
        }
    
    private:
        int   m_index;
        int   m_current;
        Type* m_storage;
    
        // No Copy
        dtFastArray& operator=(const dtFastArray& c) { return *this; }
        dtFastArray(const dtFastArray& c){}
    };
    

    Das wäre jetzt im Prinzip ein Dynamisches Array.

    im buch: "c++ lernen und professionell anwenden" gibt es einmal diese Cell
    wo in jedem Objekt ein Zeiger auf das nächste Objekt zeigt und so eine kette entsteht. wird ein objekt dazwischen zerstört, wird der zeiger umgebogen auf das nächstliegende objekt gezeigt. und falls dahinter nichts mehr ist, dann wird es auf NULL gezeigt

    Das was du hier möchtest, ist eine verkettete Liste. Das ist was ganz anderes :).
    Das wäre im Prinzp sowas:

    /*********************************************************
     * File   : dtList.h 
     * Author : D. Gentner                
     * Date   : 5.1.2007                    
     * Purpose: A linked List-Template
     * Todo   :      
     *
     * Copyright (C) 2007 D. Gentner. All rights reserved.
     * Released under the GNU General Public License V2.
     *********************************************************/
    #ifndef _DTLIST_H_
    #define _DTLIST_H_
    
    template <typename T> class dtList;
    
    /** @brief The DataStructure for dtList
      *
      * This class represents the data used in dtList.
      * It's not meant that you add the data directly to this class.
      * Please use dtList to do that.
      */
    template <typename T>
    class dtListData
    {
    public:
        inline dtListData()
        {
            m_data = NULL;
            m_next = NULL;
            m_prev = NULL;
            m_ordinal = 0;
        }
    
        inline ~dtListData()
        {
            //dtDelete(m_data);
        }
    
        /** @brief Returns a Pointer to the Data of this Object. */
        inline T* getData()
        {
            return m_data;
        }
    
        /** @brief Returns the Ordinal Number */
        inline dtUint getOrdinal()
        {
            return m_ordinal;
        }
    
        /** @brief Returns the next entry of the list */
        inline dtListData<T>* getNext()
        {
            return m_next;
        }
    
        /** @brief Returns the previous entry of the list */
        inline dtListData<T>* getPrevious()
        {
            return m_prev;
        }
    
    private:
        dtUint m_ordinal;
        T*   m_data;
        dtListData<T>* m_next;
        dtListData<T>* m_prev;
    
        friend dtList<T>;
    };
    
    /** @brief This class represents a linked List
      *
      * This class is a list for storing data in memory.
      * When you add data, the content of the pointer is copied,
      * so you should have no problems with deleting data after you added it,
      * except when the list contains pointers.
      */
    template <typename T>
    class dtList
    {
    public:
        inline dtList()
        {
            m_list     = new dtListData<T>;
            m_first    = m_list;
            m_iterator = m_first;
            m_size     = 0;
        }
    
        inline ~dtList()
        {       
            for (dtUint i=1;i<this->getSize();i++)
            {           
                dtListData<T>* next = this->getListData(i, true);
                delete next;
            }
    
            // Delete the first entry.
            dtDelete(m_first);
        }
    
        /** @brief Adds an Entry to the List
          * @param data A pointer to the Data
          * @return The ordinal number of the object.
          *
          * The data will be copied. Additionally, the method returns
          * a number associated with the entry, if you like, you can
          * keep it for faster search of the data later. Makes sense when
          * adding Objects to a global list which is used by several classes.
          *
          */
        inline dtUint add(const T* data)
        {
            // Store size before increment
            int id = m_size;
            // If not NULL, alloc space
            if (m_list->m_data == NULL) 
            {
                m_list->m_data = new T();
            }
            // Copy Data
            errno_t retval = 0;
            retval = memcpy_s(m_list->m_data, sizeof(T), data, sizeof(T));
            assert(retval == 0);
            m_list->m_ordinal = m_size;
    
            // Incr. Counter
            ++m_size;
            // Get Current Pointer
            dtListData<T> *prev = m_list;
            // Allocate next
            m_list->m_next = new dtListData<T>();
            // Set Next to current Pointer
            m_list = m_list->m_next;
            // Set Previous Pointer
            m_list->m_prev = prev;
    
            return id;
        }
    
        /** @brief Removes an Item by its ordinal number.
          * @param ordinal The item to remove by ordinal.
          * @param reset Resets the search to the first item.
          */
        inline void remove(const dtUint ordinal, const bool reset = false)
        {
            dtListData<T>* element = NULL;
            element = this->getListData(ordinal, true);
    
            if (element != NULL)
            {
                element->m_prev->m_next = element->m_next;
                element->m_next->m_prev = element->m_prev;
                delete element;
                m_size--;
            }
        }
    
        /** @brief Returns the First Node 
          *
          * 
          * Should be very useful when you want to
          * iterate through the complete list.
          */
        inline dtListData<T>* getFirst() const
        {
            return m_first;
        }
    
        /** @brief Returns the Data of the named object.
          * @param ordinal The ordinal number of the object.
          * @return A pointer to the data or NULL if not found.
          */
        inline T* getData(const dtUint ordinal) 
        {
            dtListData<T>* d = getListData(ordinal, true);
            if (d == NULL)
            {
                return NULL;
            }
            else
            {
                return d->m_data;
            }
        }
    
        /** @brief Returns the Number of Nodes in the List
          * @return The size of the list. May be zero.
          */
        inline dtUint getSize() const
        {
            return m_size;
        }
    
        /** @brief Returns the dtListData Element by ordinal Number
          * @param index The number of the node you search.
          * @param reset If you set this to true, the search will start from the first entry.
          * 
          *
          */
        dtListData<T>* getListData(const dtUint index, const bool reset = false)
        {
            dtListData<T> *it = m_first;
            for (dtUint i=0;i<this->getSize();i++)
            {
                if (it->getOrdinal() == index)
                {
                    return it;
                }
                it = it->getNext();
            }
            return NULL;
        }
    
        /** @brief Searches for a node by data
          * @param data A pointer to the Data searched.
          * @todo Implement a faster search method.
          */
        inline dtListData<T>* search(const T* data)
        {
            dtListData<T>* my = m_first;
    
            for (dtUint i=0;i<this->getSize();i++)
            {
                int retval = 0;
                retval = memcmp(my->m_data, data, sizeof(T));
                if (retval == 0)
                {
                    return my;
                }
                else
                {
                    my = my->m_next;
                }
            }
            return NULL;
        }
    
    private:
        dtListData<T>* m_first;
        dtListData<T>* m_list;
        dtListData<T>* m_iterator;
        dtUint m_size;   
    };
    
    #endif /* _DTLIST_H_ */
    

    Hier beim Code auch keine Gewähr ;).
    Entscheide Dich :D.
    rya.


Anmelden zum Antworten