Array-Klassen-Problem



  • Ich habe eine Array-Klasse geschrieben, die gibts hier(Ich übernehme keine Verantwortung für die Funktionsfähigkeit, muss ich hier nur kurz erwähnen, weils net auf der Seite steht) http://mitglied.lycos.de/glamdrink/array.php.

    Zum testen habe ich folgenden Code geschrieben:

    #include "MyArray.h" //Header mit der Klasse
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	Array<int> intArray(10);
    	Array<int> otherArray(10);
    	intArray[0] = 0;
    	intArray[1] = 1;
    	intArray[2] = 2;
    	intArray.sort();
    	for(int i = 3; i < 10; ++i)
    	{
    		intArray[i] = i;
    	}
    	otherArray = intArray; 
    	otherArray.resize(12);
    	otherArray[10] = 10;
    	otherArray[11] = 11;
    	for(int a=0; a<12; ++a)
    	{
    		cout << otherArray[a] << endl;
    	}
    	return 0;
    }
    

    otherArray[] 1, 2 und 3 sind total konfuse Zahlen, der Rest stimmt. ES muss irgendwie an sort() liegen, denn wenn ich das weglasse ist alles OK und wenn ich reverse_sort() verwende geht auch alles.

    Was ist falsch?

    [edit] URL geändert[/edit]



  • Kannst du mal den richtigen Header posten? Ich will nicht raten, ob das fehlende = im CTor der einzige Fehler ist.

    The Code is exception-save

    Einfach überall try..catch(...) {} ist aber nicht, was man darunter versteht 😉



  • Verstehe ich nicht, welchen Header, es gibt nur einen, welches fehlende= im Ctor?

    Was ist denn dann exception-savety?

    thx
    Glamdring



  • im ctor steht Range normal::value; obwohl Range eine Variable ist. Offensichtlich ist Range = normal::value; gemeint. Ich würd einfach gern den echte Code ohne Syntaxfehler sehen. Weiter unten sind übrigens ein paar < nicht in < umgewandelt, wodurch von einer Funktion nur das «template» übrig geblieben ist ...

    Exception Safety: Gibt es in 3 Stufen. Erstens, die Basisgarantie (basic guarantee): Solcher Code hinterlässt beim Werfen einer Exception alle beteiligten Objekte in einem Zustand, in dem sie sauber zerstört werden können. Zweitens, die Starke Garantie (strong guarantee): Solcher Code hinterlässt beim Werfen einer Exception alle Objekte unverändert. Drittens, nothrow guarantee (mir fällt nix griffiges auf deutsch ein): Solcher Code wirft keine Exceptions.

    Was macht dein Code? Nehmen wir z.b. den Zuweisungsoperator:

    template <class T> Array<T>& Array<T>::operator=(const Array<T>& rhs)
    {
    	if (*this == rhs)
    	{
    		return *this;
    	}
    	else
    	{
    		delete[] Ar;
    		Range = rhs.size();
    		try
    		{
    			Ar = new T[Range];
    			for(int i=0; i<Range; ++i)
    			{
    				Ar[i] = rhs[i]; 
    			}
    		}
    		catch(...){}
    		return *this;
    	}
    }
    

    Im try-Block findet sich ein new. Wirft dieses ein bad_alloc, wird die Exception verschluckt, und keine Zuweisung findet statt. Allerdings verbleibt der Pointer Ar in einem ungültigen Zustand, da er vorher deleted wurde. Du kannst mit diesem Objekt jetzt nichts mehr anfangen, und im Destruktor fliegt dir das doppelte delete um die Ohren. Deine catch(...)-Blöcke verschlucken nur Exceptions, die idR von ernsthaften Problemen herrühren, tragen aber nichts zur Exceptionsicherheit bei.



  • Das mit den Exceptions ist interessant, aber das ist der Echte Code 😃 VC++ hat den ohne Probleme durchgehen lassen, es ist nur der Laufzeitfehler aufgetreten.

    mfg
    Glamdring



  • Ok, ich habe den Copde jetzt verbessert und nochmal online gestellt, sowohl VC++ als auch GCC lassen den Code durchgehen.

    mfg
    Glamdring



  • Deine try-Blöcke machen die Klasse auch weiterhin nur unsicherer als sie es ohne die Blöcke wäre. Lass sie einfach weg und Array erfüllt immerhin die Grundgarantie, soweit ich das sehe...
    Außerdem wäre delete[] vielleicht angebrachter. Einen Kopierkonstruktor sehe ich auch nicht *mecker*



  • Stimmt, den Copy-Koinstruktor hab ich einfach vergessen und das mit den Exceptions muss ich noch verbessern (auch wenn das nur indirekt, bzw. garnicht mit der Frage zu tun hat).

    mfg
    Glamdring



  • Wozu eigentlich ein sort() im Array?
    std::sort ist die bessere Variante. Notfalls einfach std::sort spezialisieren.



  • Shade: Dazu müsste er Iteratoren anbieten 😉

    Was ist eigentlich der Grund, dass es sowohl erase als auch assign gibt? Mir scheint, beide tun von aussen sichtbar das gleiche, nur dass erase Pointer auf Array-Elemente ungültig macht.



  • Bashar schrieb:

    Shade: Dazu müsste er Iteratoren anbieten 😉

    Naja, das ist bei mir Grundvorauussetzung bei einem Container. Ohne macht er ja nicht sonderlich viel Sinn


Anmelden zum Antworten