Iterator



  • blurry333 schrieb:

    Hab selber gar was gefunden.

    Der zuweisungsoperator muss keinen Speicher anfordern.
    Beim Copy Konstruktor hingegen existiert noch kein Speicher, da das
    Objekt erst angelegt wird.

    von der sache her richtig - allerdings würde ich es eher anders formulieren.
    beim =operator muss zuerst das alte objekt zerstört werden und dann kann erst das neue konstruiert werden. (die reihenfolge wird aber oftmals nicht eingehalten, weil er durch das copy-and-swap-idiom(->google) exceptionsicher gemacht werden kann, man keine code-duplizierungen hat und wenn überhaupt allenfalls minimal messbare performance-unterschiede entstehen.
    aber wie schon gesagt, solltest du hier weder copyctor noch assignment-op implementieren, sondern einfach nur als private deklarieren.

    bb



  • muss man nicht eigentlich auch noch operator=() überladen? <kram code raus>

    class Single{
    private:
       Single(){};                  //  can not be called
       Single(Single const&){};     //  can not be copyed
       Single& operator=(Single const&){};  // can not be reassigned
    
    public:
        static Single* getInstance(); 
        // ... methods that make sense ...
    
    private:
        static Single* singled;
    };
    
    Single* Single::singled = NULL;
    
    Single * Single::getInstance()
    {
        if (! singled) singled = new Single();
    
        return singled;
    }
    


  • hab ich doch gerade schon geschrieben...

    padreigh schrieb:

    class Single{
    private:
    /*
       Single(){};                  //  can not be called
       Single(Single const&){}; //NEIN!
       Single& operator=(Single const&){}; //NEIN!
    */
      Single() {}
      Single(const Single&); //LNK error if called
      Single& operator=(const Single&); //LNK error if called
    public:
        static Single* getInstance(); 
        // ... methods that make sense ...
    
    private:
        static Single* singled;
    };
    
    Single* Single::singled = NULL;
    
    Single * Single::getInstance()
    {
        if (! singled) singled = new Single();
    
        return singled;
    }
    

    Nachteil an dieser Lsg. ist, dass sie nicht thread-safe ist.
    die static-Methode ist wenigstens im GCC thread-safe. im msvc glaube ich aber (noch?) nicht.

    bb



  • unskilled schrieb:

    [...]von der sache her richtig - allerdings würde ich es eher anders formulieren.
    beim =operator muss zuerst das alte objekt zerstört werden und dann kann erst das neue konstruiert werden.[...]

    Wieso das denn?



  • Tachyon schrieb:

    unskilled schrieb:

    [...]von der sache her richtig - allerdings würde ich es eher anders formulieren.
    beim =operator muss zuerst das alte objekt zerstört werden und dann kann erst das neue konstruiert werden.[...]

    Wieso das denn?

    Mit "altes Objekt" ist das Objekt gemeint, dem ein neuer Wert zugewiesen werden soll. Z.B. muss ein vector in seinem op= zuerst seine alten Elemente freigeben, bevor er die neuen kopieren kann. Im Copy-Ctor entfällt das, da es keine alten Elemente gibt.



  • Tachyon schrieb:

    unskilled schrieb:

    [...]von der sache her richtig - allerdings würde ich es eher anders formulieren.
    beim =operator muss zuerst das alte objekt zerstört werden und dann kann erst das neue konstruiert werden.[...]

    Wieso das denn?

    weil

    Der zuweisungsoperator muss keinen Speicher anfordern.
    Beim Copy Konstruktor hingegen existiert noch kein Speicher, da das
    Objekt erst angelegt wird.

    der zuweisungsoperator muss sehr wohl (unter umständen) speicher anfordern.
    beim eintritt in den copyctor existiert der speicher genau genommen schon und er muss nur noch initialisiert werden.

    bb



  • ipsec schrieb:

    Z.B. muss ein vector in seinem op= zuerst seine alten Elemente freigeben, bevor er die neuen kopieren kann.

    Nein. Das wäre ganz schlecht im Bezug auf Exceptionsicherheit.

    unskilled schrieb:

    beim eintritt in den copyctor existiert der speicher genau genommen schon und er muss nur noch initialisiert werden.

    Woher kommt der bereits existierende Speicher, wenn er nicht im Kopierkonstruktor angefordert werden muss?



  • Nexus schrieb:

    ipsec schrieb:

    Z.B. muss ein vector in seinem op= zuerst seine alten Elemente freigeben, bevor er die neuen kopieren kann.

    Nein. Das wäre ganz schlecht im Bezug auf Exceptionsicherheit.

    Ich meinte das anschaulich: beim op= gibt es noch Elemente, um die sich irgendwie gekümmert werden muss, beim CopyCtor nicht. Wie jetzt die konkrete Implementierung aussieht, weiß ich nicht.



  • ipsec schrieb:

    Ich meinte das anschaulich: beim op= gibt es noch Elemente, um die sich irgendwie gekümmert werden muss, beim CopyCtor nicht.

    Okay. Ich würde nur generell von dem Schema wegkommen, dass bei einer Zuweisung zuerst der alte Wert zerstört und dann der neue neu konstruiert werden muss. Bei komplexeren Implementierungen geschieht das oft umgekehrt, um im Fehlerfall keine Zombie-Objekte zu haben.

    Denk dran, dass bei solch schematischen Implementierungen bereits sowas einen schwerwiegenden Fehler darstellt. Und das darf nicht sein. Eine explizite Abfrage im operator= löst das Gesamtproblem übrigens auch nur bedingt.

    MyClass a;
    a = a;
    

    ipsec schrieb:

    Wie jetzt die konkrete Implementierung aussieht, weiß ich nicht.

    Schau dir mal das Copy-and-Swap-Idiom an. Damit kannst du neben allen anderen Vorteilen auch Codeduplizierung vermeiden, indem du im Zuweisungsoperator den Kopierkonstruktor verwendest.



  • Sicher, dass vector auf copy-and-swap setzt? Ich meine gehört zu haben, dass der zusätzliche temporäre Speicherplatz in der Größe des zu kopierenden vectors mit der Designphilosophie der Standardbibliothek unvereinbar ist.



  • Nein, ich bin mir nicht sicher, ich meinte den Absatz mit Copy-and-Swap eher allgemein. Möglicherweise wird bei std::vector::operator= nur die schwache Exception-Garantie durchgesetzt, wie bei std::copy() . Aber zumindest beim Vergrössern könnte die starke Garantie genutzt werden.

    Ich wollte vor allem sagen, dass der std::vector den Speicherplatz der alten Objekten keinesfalls freigeben muss, wie du es geschrieben hast.

    Container sind hier sowieso etwas speziell, weil ihre Instanzen unterschiedlich viel Speicherplatz verwenden. Daher kann Copy-and-Swap performancemässig nicht so der Hit sein, da hast du völlig Recht. Sonst ist es allerdings oft ein sinnvolles Idiom.


Anmelden zum Antworten