Iterator



  • jo jetzt gehts.

    warum brauch ich im main unbedingt die Referenz.

    Singleton x=Singleton::getInstance(); // geht nicht
    
    Singleton& x=Singleton::getInstance(); // geht
    

    Ok klar ist wenns keine Referenz wär könnte man mehr als ein objekt anlegen.
    Aber in meinem obigen Bespiel gings ja auch ohne .



  • Blackskyliner schrieb:

    Ergo das hier fehlt:

    Singleton::Singleton(const Singleton& cc){}
    

    Nein, das hier wird nicht implementiert.



  • blurry333 schrieb:

    jo jetzt gehts.

    warum brauch ich im main unbedingt die Referenz.

    Singleton x=Singleton::getInstance(); // geht nicht
    
    Singleton& x=Singleton::getInstance(); // geht
    

    weil du ein singleton _nicht_ kopieren oder zuweisen kannst.

    ps: immernoch diese drecks spam-sperre -.-



  • Huch, da wahr ich wohl etwas zu übereifrig mit implementieren 🙂
    Aber ist es nicht eigentlich egal, wenn man den copy private setzt?
    Ist es insofern unerwünscht, damit man IN der Singleton nicht versehentlich kopiert?



  • hier wird ja auch eine Referenz zurückgeliefert.
    Trotzdem gehts.

    #include <iostream> 
    #include <stdio.h> 
    
    using namespace std; 
    
    int& funk(int& x) 
    { 
    	static int z;
        return z; 
    } 
    
    int main() 
    { 
         int p=7; 
        int zahl; 
    
        zahl=funk(p);  // obwohl zahl keine Referenz 
                       // funktionierts 
    
    }
    


  • Du weist eine Referenz zu. d.H. du ruft den Copy-konstruktor von int auf, wenn es denn eine Klasse wäre.

    Da der Copy ja von deiner Singleton ja aber vom Konzept her private ist, kann man das nicht machen.

    zahl, hält somit nicht die direkte Referenz auf das static Element, sondern eine eigene Kopie.



  • OK :)))



  • Der CopyKonstruktor wird wohl immer bei der Initialisierung aufgerufen ?

    Die Implementierung von Zuweisungsoperator und CopyKonstruktor müßte doch
    exakt dieselbe sein ?



  • 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.



  • Blackskyliner schrieb:

    Huch, da wahr ich wohl etwas zu übereifrig mit implementieren 🙂
    Aber ist es nicht eigentlich egal, wenn man den copy private setzt?
    Ist es insofern unerwünscht, damit man IN der Singleton nicht versehentlich kopiert?

    wieso sollte man etwas (falsch) implementieren, wenn man es doch gar nicht braucht? so gar: wenn man verhindern will, dass es verwendet wird.
    üblicherweise setzt man so gar noch den assignment-operator private (und auch hier implementiert man nichts). ist zwar in meinen augen überflüssig, aber schaden kann auch das nicht.

    bb



  • 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.


Anmelden zum Antworten