Was haltet ihr von meiner eigenen CONTAINER Klasse?



  • [unsinn]



  • @Don06

    array<T>& operator = (const array<T> &other) // Selbstzuweisung?
    

    alternative??

    Grüüüße



  • zeusosc schrieb:

    @Don06

    array<T>& operator = (const array<T> &other) // Selbstzuweisung?
    

    alternative??

    Grüüüße

    Don06 meinte damit wohl das eine mögliche Selbstzuweisung aktuell nicht behandelt wird.

    Edit:
    Was mir nach auffiel

    o array(u32 size) sollte explizit sein
    o Vergleichsoperatoren halte ich für unnötig
    o Die Const-Correctness wurde nicht konsequent eingehalten (z.B. size())
    o Die "Wachstumsstrategie" ist weniger optimal (viel zu viel Allokationen)
    o Kein Kopierkonstruktor
    o Kein korrektes Exceptionhandling, gerade bei Neuanforderung von Speicher. Das kann schnell zu ungültigen Zeigern und haufwenweisen Problemen führen.



  • Abgesehn von der Definition des "iterator"s und des "const_iterator"s sieht das jetzt aber schon relativ gut aus, oder?!



  • David_pb schrieb:

    zeusosc schrieb:

    @Don06

    array<T>& operator = (const array<T> &other) // Selbstzuweisung?
    

    alternative??

    Grüüüße

    Don06 meinte damit wohl das eine mögliche Selbstzuweisung aktuell nicht behandelt wird.

    Edit:
    Was mir nach auffiel

    o array(u32 size) sollte explizit sein
    o Vergleichsoperatoren halte ich für unnötig
    o Die Const-Correctness wurde nicht konsequent eingehalten (z.B. size())
    o Die "Wachstumsstrategie" ist weniger optimal (viel zu viel Allokationen)
    o Kein Kopierkonstruktor
    o Kein korrektes Exceptionhandling, gerade bei Neuanforderung von Speicher. Das kann schnell zu ungültigen Zeigern und haufwenweisen Problemen führen.

    ok,..
    Wie behandelt man korrekterweise eine Selbstzuweisung??
    Ich benutze eine ähnliche "Wachsutmsstrategie". Wie kann man das vermeiden?? (ausser nutzung std::container á la vector)
    Wie sieht eine korrekte Fehlerbehandlung bei neuanforderung von speicher aus, ausser das das System sagt "hmmm, nö!".
    *abo*
    grüüße



  • zeusosc schrieb:

    Wie behandelt man korrekterweise eine Selbstzuweisung??

    Die schlechte Methode:

    if(this == &other)

    die gute Methode:
    operator= mit Hilfe des CopyCtors so implementieren:

    T& operator=(T const& other) {
      T temp(other);
      swap(temp);
      return *this;
    }
    

    Ich benutze eine ähnliche "Wachsutmsstrategie". Wie kann man das vermeiden?? (ausser nutzung std::container á la vector)

    Standardmaessig nimmt man mal 1,3 oder 1,5 wenn man aggresiv vorgeht mal 2.

    Wie sieht eine korrekte Fehlerbehandlung bei neuanforderung von speicher aus, ausser das das System sagt "hmmm, nö!".

    du wirfst eine exception und sagst: sorry, kann den container nicht vergroessern - aber der container bleibt dennoch in einem ordentlichen zustand, lediglich die einfuege operation ist fehlgeschlagen.



  • LukasBanana schrieb:

    /* Operators - comparision */
            
            bool operator == (array<T> other)
            {
                /* Check if the arrays are not emtpy */
                if (!data_ || !other.data_)
                    return false;
                
               ...
            
            bool operator != (array<T> other)
            {
                /* Check if the arrays are not emtpy */
                if (!data_ || !other.data_)
                    return false;
    

    Zweimal die gleiche Bedingung mit dem selben Rückgabewert in gleich und ungleich? 😕 Die selben beiden Container können also gleichzeitig weder gleich noch ungleich sein. 😮



  • Shade Of Mine schrieb:

    Die schlechte Methode:

    if(this == &other)

    Weshalb ist diese Methode schlechter? Weil man mehr Code schreiben muss, anstatt bereits Existierendes (Kopierkonstruktor) wiederzuverwenden?

    Antilogik schrieb:

    Zweimal die gleiche Bedingung mit dem selben Rückgabewert in gleich und ungleich? 😕 Die selben beiden Container können also gleichzeitig weder gleich noch ungleich sein. 😮

    Da könnte man auch den einen Operator durch den (negierten) anderen ausdrücken.



  • Nexus schrieb:

    Shade Of Mine schrieb:

    Die schlechte Methode:

    if(this == &other)

    Weshalb ist diese Methode schlechter? Weil man mehr Code schreiben muss, anstatt bereits Existierendes (Kopierkonstruktor) wiederzuverwenden?

    http://www.gotw.ca/gotw/011.htm 😉



  • Nach deinem Link sind Argumente gegen if (this != &other) eine überflüssige Prüfung auf Zuweisung bei exception-sicherer Umgebung und eine Gefahr durch überladenen operator& , soweit ich das verstanden habe. Aber wird der Adressoperator in der Praxis häufig überladen?

    Und bei der anderen Methode (Copy and Swap) wird immerhin ein temporäres Objekt erzeugt, ist das nicht langsamer? Oder wird das wegoptimiert?



  • Ich bezweifle stark, dass sich bei der «besseren» Methode die Temporäre Kopie vermeiden lässt, da jene Kopie an sich diese Methode «sicherer» macht. Jedenfalls habe ich das so verstanden.

    Kommt allerdings mehr als nur etwas auf die Implementierung von swap() an wie sehr das ein Problem ist. Bei einer std::list z.B. stell' ich mir das wenig problematisch vor.



  • Um das Thema dieses Threads nicht weiter zu behindern, habe ich die Diskussion in einen eigenen Thread ausgelagert.



  • darthdespotism schrieb:

    Nexus schrieb:

    Shade Of Mine schrieb:

    Die schlechte Methode:

    if(this == &other)

    Weshalb ist diese Methode schlechter? Weil man mehr Code schreiben muss, anstatt bereits Existierendes (Kopierkonstruktor) wiederzuverwenden?

    http://www.gotw.ca/gotw/011.htm 😉

    was steht da??



  • ich verstehe es nicht

    pech



  • 👎

    If operator=() is exception-safe, you don't need to test for self-assignment.

    Warum, was heißt exception-safe?

    There are two efficiency downsides, however: a) if you can test for self-assignment then you can completely optimize away the assignment;

    Wenn ich auf Selbstzuweisung überprüfen kann, kann ich die Zuweisung komplett wegoptimieren? Was soll das bedeuten?

    Since classes may provide their own operator&(), the test in question may do something completely different than intended. This comes under the heading of "protecting against Machiavelli" because presumably the writer of operator=() knows whether or not his class also overloads operator&().

    Note that while a class may also provide a T::operator!=(), it's irrelevant since it can't interfere with this test. The reason is that you can't write an operator!=() that takes two T* parameters since at least one parameter to an overloaded operator must be of class type.

    Was hat es mit Machiavelli auf sich? Und den zweiten Absatz verstehe ich so gut wie gar nicht. Wieso kann ich keinen Operator schreiben, der zwei T* erwartet?

    Here's a "code joke". Believe it or not, it's been tried by well-meaning but clearly misguided coders:
    T::T( const T& other ) {
    if( this != &other ) {
    // ...
    }
    }

    Besteht der Witz darin, dass man Objekte gar nicht mehr kopieren kann?

    Vielleicht macht sich ja jemand die Mühe. 🙄




  • Mod

    ich verstehe es nicht schrieb:

    👎

    If operator=() is exception-safe, you don't need to test for self-assignment.

    Warum, was heißt exception-safe?

    google, faq und Artikel sind dein Freund.

    There are two efficiency downsides, however: a) if you can test for self-assignment then you can completely optimize away the assignment;

    Wenn ich auf Selbstzuweisung überprüfen kann, kann ich die Zuweisung komplett wegoptimieren? Was soll das bedeuten?

    unter bestimmten Umständen.

    Since classes may provide their own operator&(), the test in question may do something completely different than intended. This comes under the heading of "protecting against Machiavelli" because presumably the writer of operator=() knows whether or not his class also overloads operator&().

    Note that while a class may also provide a T::operator!=(), it's irrelevant since it can't interfere with this test. The reason is that you can't write an operator!=() that takes two T* parameters since at least one parameter to an overloaded operator must be of class type.

    Was hat es mit Machiavelli auf sich? Und den zweiten Absatz verstehe ich so gut wie gar nicht. Wieso kann ich keinen Operator schreiben, der zwei T* erwartet?

    Du müsstest dafür "Der Fürst" lesen. Hier ist jemand gemeint, der absichtlich gegen diese vernünftigen Regeln verstößt. 2. FAQ - Operatorüberladung benötigt wenigstens einen Parameter, der ein UDT ist.

    ich verstehe es nicht schrieb:

    Here's a "code joke". Believe it or not, it's been tried by well-meaning but clearly misguided coders:
    T::T( const T& other ) {
    if( this != &other ) {
    // ...
    }
    }

    Besteht der Witz darin, dass man Objekte gar nicht mehr kopieren kann?

    Stell dir einfach die Frage, unter welchen Umständen dieser Test fehlschlagen kann.


Anmelden zum Antworten