Verbesserung an Template Klasse gegen Array Überlauf



  • template<class typ,int size> class MyArray {
    

    warum ist size ein template-argument? kannst doch beruhigt die initial size auf 64 festegen oder als konstruktorargument nehmen. vorteil: nicht jedes array braucht eigenen code und die exe wird kleiner, das programm am ende scneller.

    MyArray(); 
                   MyArray(const MyArray &Array_kopie); 
                   MyArray(typ* arr); 
    
                   typ operator=(const MyArray& a); 
                   typ &operator[] (unsigned int i); 
                   const typ &operator[](unsigned int i) const; 
    
                    ~MyArray() { delete [] array; }
    

    besser, man macht konstruktoren, zuweisungsop und dtor zusammen.

    MyArray(); 
                   MyArray(typ* arr); 
                   MyArray(const MyArray &Array_kopie); 
                   typ operator=(const MyArray& a); 
                    ~MyArray() { delete [] array; } 
    
                   typ &operator[] (unsigned int i); 
                   const typ &operator[](unsigned int i) const;
    

    und der rückgabetyp des op= ist gelinde gesagt gewagt.

    template<class typ,int size> MyArray<typ,size>::MyArray() 
    { 
                   aktSize=size; 
                   array=new typ[size]; 
    }
    

    leider muss das umgeschrieben werden zu

    template<class typ,int size> MyArray<typ,size>::MyArray() 
    :array(new typ[size])//das hier wichtig für wenn exceptions
    ,aktSize(size)
    { 
    }
    
    template<class typ,int size> MyArray<typ,size>::MyArray(typ* arr) 
    { 
                   aktSize=size; 
                   array=new typ[size]; 
    
                   for(int i=0;i<size;i++) 
                   array[i]=arr[i]; 
    
    }
    

    naja, wollen wir nicht doch lieber begin und end übergeben? so isses ein wenig komisch.

    template <class typ,int size> const typ &MyArray<typ,size>::operator[](unsigned int i) const   
    { 
                  if(i<aktSize) 
                                return array[i]; 
                  else 
                                throw out_of_range("Out of Range !!!");   
    
    }
    

    was soll das denn? das widerstebt mir. irgendwas ist da ganz komisch.

    return *this;     // Ist nicht zwigend erforderlich oda ?
    

    doch. für

    a=b=c;
    
    typ* temparray; //keine variablen leer stehen lassen
    

    und mach dazu noch ein StaticArray, das nicht wachsen kann und nicht new benutzt.



  • volkard schrieb:

    template<class typ,int size> class MyArray {
    

    warum ist size ein template-argument? kannst doch beruhigt die initial size auf 64 festegen oder als konstruktorargument nehmen. vorteil: nicht jedes array braucht eigenen code und die exe wird kleiner, das programm am ende scneller.

    Stimmt. Hast vollkommen recht 😃
    Das dann für jedes Array nen eigener Code erzeugt wird, daran hab ich nicht gedacht... 😃

    volkard schrieb:

    MyArray(); 
                   MyArray(const MyArray &Array_kopie); 
                   MyArray(typ* arr); 
                  
                   typ operator=(const MyArray& a); 
                   typ &operator[] (unsigned int i); 
                   const typ &operator[](unsigned int i) const; 
                                  
                    ~MyArray() { delete [] array; }
    

    besser, man macht konstruktoren, zuweisungsop und dtor zusammen.

    Sind doch !!?? 😕 😕 Oder meinste alle auf einen Haufen.

    volkard schrieb:

    MyArray(); 
                   MyArray(typ* arr); 
                   MyArray(const MyArray &Array_kopie); 
                   typ operator=(const MyArray& a); 
                    ~MyArray() { delete [] array; } 
    
                   typ &operator[] (unsigned int i); 
                   const typ &operator[](unsigned int i) const;
    

    und der rückgabetyp des op= ist gelinde gesagt gewagt.

    O man. Upps soll natürlich MyArray heißen...

    volkard schrieb:

    leider muss das umgeschrieben werden zu

    template<class typ,int size> MyArray<typ,size>::MyArray() 
    :array(new typ[size])//das hier wichtig für wenn exceptions
    ,aktSize(size)
    { 
    }
    

    Von dem Code verstehe ich nur Bahnhooof 😕

    volkard schrieb:

    naja, wollen wir nicht doch lieber begin und end übergeben? so isses ein wenig komisch.

    Ok OK 🕶

    volkard schrieb:

    template <class typ,int size> const typ &MyArray<typ,size>::operator[](unsigned int i) const   
    { 
                  if(i<aktSize) 
                                return array[i]; 
                  else 
                                throw out_of_range("Out of Range !!!");   
            
    }
    

    was soll das denn? das widerstebt mir. irgendwas ist da ganz komisch.

    Habe ich nen Reh umgefahren ??? Was ist daran komisch 😕

    volkard schrieb:

    typ* temparray; //keine variablen leer stehen lassen
    

    Wie wo was ???? Was ist den daran Leer 😕

    volkard schrieb:

    und mach dazu noch ein StaticArray, das nicht wachsen kann und nicht new benutzt.

    Meinst du noch ne Template-Klasse mit normalen Arrays ?



  • genau, ne template klasse mit normalen arrays. dann hat wenigsten der template parameter "size" einen sinn 😃



  • Was bringt mir dann diese Klasse. Was soll ich denn da bei einem Arrayüberlauf machen? --> Nichts einfach so lassen oder ???



  • Freak_Coder schrieb:

    Was bringt mir dann diese Klasse. Was soll ich denn da bei einem Arrayüberlauf machen? --> Nichts einfach so lassen oder ???

    assert //ziemlich gut
    oder
    __asm int 3 //lustig, doch hilfreich
    oder
    throw //pass nicht zum c++-stil

    oder ganz perfekt ein eigenes ASSERT, was erst asm int 3 macht (aber nur wenn ein debugger mitläuft) und dann throw (ne eigene exception-klasse mit __LINE__ und __FILE__ übergeben).

    ach, mach erstmal einfach assert. indexgrenzenüberschreitungen sind halt so häufige fehler und mit ner eigenen array-klasse so einfach wegzumachen, daß man eigenlich immer ne eigene klasse nehmen sollte.



  • Ok! Weiß zwar noch nicht über asserts aber kann mir ja das Wissen aneignen 😃

    Wäre mal gut wenn du mal auf Seite 4 schauen würdest da habe ich dir noch ne Menge fragen gestellt(letzer Beitrag(Die assert frage hat sich dann wohl da geklärt))...



  • Freak_Coder schrieb:

    Wäre mal gut wenn du mal auf Seite 4 schauen würdest da habe ich dir noch ne Menge fragen gestellt(letzer Beitrag...

    dachte, alles sei geklärt.

    mit leer meinte ich uninitialisiert. siehe http://www.volkard.de/Cpp/Tutorial/Grundlagen/Variablen/index.html

    und ja, ich meine eine array-klasse um ein normales array. der wunsch müßte auf seite 1 schon stehen.

    template<class typ,int size> class MyArray {
    	typ array[size];
        public: 
    	typ &operator[] (unsigned int i); 
        const typ &operator[](unsigned int i) const; 
    };
    

    und in die op[] fein assert oder irgendwas rein.



  • Wenn ich das richtig gesehen habe gibt der op= immer noch ne Kopie zurück und ist damit noch etwa doppel so langsam wie er sein müßte.



  • Habe jetzt meine Klasse wieder umgeändert, nur gibt es etwas was ich noch nicht verstehe:

    template<class typ,int size> MyArray<typ,size>::MyArray() 
    :array(new typ[size])// Mit dieser schreibweise ruft man doch ander Ctors auf oda
    ,aktSize(size)        // aber was hat array() und aktSize() da zu suchen (nichts kapisch)
    { 
    }
    

    Einer ne Erklärung vielleicht oder nen Link ???



  • Freak_Coder schrieb:

    Einer ne Erklärung vielleicht oder nen Link ???

    weder noch. ich hab da gelogen. deine version ist hübscher.



  • 😕 😕 Häää, wenn das so ist !
    Aber gibt es diese Schreibweise wirklich oder auch gelögen oda ??? 😕

    Und was war damit:

    volkard schrieb:

    template <class typ,int size> const typ &MyArray<typ,size>::operator[](unsigned int i) const   
    { 
                  if(i<aktSize) 
                                return array[i]; 
                  else 
                                throw out_of_range("Out of Range !!!");   
            
    }
    

    was soll das denn? das widerstebt mir. irgendwas ist da ganz komisch.

    Ist da auch was gelogen oder? Caipi meinte ich solls so machen ?



  • Freak_Coder schrieb:

    😕 😕 Häää, wenn das so ist !
    Aber gibt es diese Schreibweise wirklich oder auch gelögen oda ??? 😕

    die gibt es. und irgendwann wird sie besser als die jetzige. im moment ist die jetzige besser weil übersichtlicher.

    Und was war damit:

    volkard schrieb:

    was soll das denn? das widerstebt mir. irgendwas ist da ganz komisch.

    Ist da auch was gelogen oder? Caipi meinte ich solls so machen ?

    das widerstebt mir wirklich. irgendwas ist da wirklich ganz komisch.

    das klint so, als wolle man programmierfehler zur laufzeit fangen und heilen.



  • Weil ich irgendwie nicht verstehe was du meinst werde ich es einfach mal rausnemen und nur ein return (vorerst) reinsetzten.



  • Hier nun nochmal alles:

    template<class typ> class MyArray {
    
                   typ* array;
                   int aktSize;
                   void grow(size_t newSize);
        public:
                   MyArray(size_t size);
                   MyArray(const MyArray &Array_kopie);
                   MyArray(size_t size,typ* arr_anfang,typ* arr_ende);
    
                   MyArray &operator=(const MyArray& a);
                   typ &operator[] (unsigned int i);
                   const typ &operator[](unsigned int i) const;
    
                    ~MyArray() { delete [] array; }
    
    };
    
    template<class typ> MyArray<typ>::MyArray(size_t size)
    {
                   aktSize=size;
                   array=new typ[size];
    }
    
    template<class typ> MyArray<typ>::MyArray(const MyArray &Array_kopie)
    {
                  array=new typ[Array_kopie.aktSize];
                  aktSize=Array_kopie.aktSize;
                  for(int i=0;i<Array_kopie.aktSize;i++)
                           array[i]=Array_kopie.array[i];
    }
    
    template<class typ> MyArray<typ>::MyArray(size_t size,typ* arr_anfang, typ* arr_ende)
    {
                   aktSize=size;
                   array=new typ[size];
    
                   for(int i=0;&(arr_anfang[i])!=arr_ende;i++)
                   array[i]=arr_anfang[i];
    
    }
    
    template <class typ> typ &MyArray<typ>::operator[](unsigned int i)
    {
             if(i>aktSize) grow(i);
             return array[i];
    }
    
    template <class typ> const typ &MyArray<typ>::operator[](unsigned int i) const
    {
                  return array[i];
    }
    
    template <class typ> MyArray<typ> &MyArray<typ>::operator=(const MyArray& a )
    {
             if(aktSize<a.aktSize)
             {
               delete [] array;
               array=new typ[a.aktSize];
             }
    
             MyArray temp(a);
             std::swap(array,temp.array);
             std::swap(aktSize,temp.aktSize);
    
             return *this;     
    }
    
    template <class typ> void MyArray<typ>::grow(size_t newSize)
    {
             int altSize=aktSize;
    
             aktSize=newSize * 2;
    
             typ* temparray=new typ [aktSize];
    
             for(int i=0;i<altSize;i++)
                     temparray[i]=array[i];
    
             delete [] array;
             array=temparray;
    
    }
    
    //----------------------------------------------------------------------------
    
    template <class typ,size_t size> class StaticArray {
    
                    typ array[size];
            public:
                    StaticArray() { }
                    StaticArray(typ* arr_anfang,typ* arr_ende);
    
                    typ &operator[] (unsigned int i);
                    const typ &operator[](unsigned int i) const;
    
    };
    
    template<class typ,size_t size> StaticArray<typ,size>::StaticArray(typ* arr_anfang, typ* arr_ende)
    {
                   for(int i=0;&(arr_anfang[i])!=arr_ende;i++)
                   array[i]=arr_anfang[i];
    
    }
    
    template <class typ,size_t size> typ &StaticArray<typ,size>::operator[](unsigned int i)
    {
                  assert(i<size);
                  return array[i];
    }
    
    template <class typ,size_t size> const typ &StaticArray<typ,size>::operator[](unsigned int i) const
    {
                  assert(i<size);
                  return array[i];
    }
    

    In was für einen Datei speichert man am besten nun so was ab um nachher damit in eigenen Programmen arbeiten zu können.

    Und sonst alles diesmal in ORDNUNG ....



  • das ganze kommt am besten in einen eigenen header, also eine *.hpp 🙂


Anmelden zum Antworten