Zuweisung



  • Original erstellt von Steven:
    @Dimah: Schaut interressant aus... Aber ist vielleicht etwas langsam. Trotzdem danke!

    langsamer? du sparst dir ein if!!
    ein swap ist nicht nur exception sicher und schön, sondern ist auch sau schnell - denn es ermöglicht folgendes:

    a.swap(b);
    und schon wird nichts kopiert.

    wenn du folgendes meinst:
    a=a;
    dann tut mir der programmierer leid - da wird er mit den kosten des kopierens leben müssen, oder er sucht sich nen anderen job...



  • @kingruedi: Hab's mir durchgelesen, versteh' aber ehrlich gesagt nur Bahnhof... 😕
    @Shade Of Mine: Langsam ist es wegen der temporären Kopie, die erzeugt wird, wenn man das Quellobjekt nicht per Referenz übergibt. Außerdem muss swap auch eine temporäre Kopie erzeugen.

    a.swap(b);
    und schon wird nichts kopiert.

    😕



  • Original erstellt von Steven:
    Langsam ist es wegen der temporären Kopie, die erzeugt wird, wenn man das Quellobjekt nicht per Referenz übergibt. Außerdem muss swap auch eine temporäre Kopie erzeugen.

    swap auf buildin kann der compilier so optimieren das er keine temp var braucht

    Original erstellt von Steven:
    [quote]a.swap(b);
    und schon wird nichts kopiert.

    😕 [/QUOTE]
    er meint das compilier das inlinen kann und das dann zu das auflösen kann, aber wissen ist besser als glauben

    wenn du den swap weg nicht gehen willst, erstmal würde ich alle ifs durch asserts ersetzen denn wie Shade Of Mine sagte, ich mache mein programm doch nicht langsammer durch ein if was ich nie brauche, selbs wenn ich sowas machen würde

    map<string, foo> m;
    //...
    cin >> von;
    cin >> nach;
    m[nach] = m[von];
    

    fange ich das dann ab mit einen if(von != nach)

    ahja und zu

    class special_class : public some_class, public base_class
    

    kanns du da noch ein bsp ausarbeiten, weil ich das schwer kapierer



  • Original erstellt von Dimah:
    swap auf buildin kann der compilier so optimieren das er keine temp var braucht

    ...und bei strings und Arrays wird's richtig gemütlich langsam 😞

    Original erstellt von Dimah:
    **wenn du den swap weg nicht gehen willst, erstmal würde ich alle ifs durch asserts ersetzen denn wie Shade Of Mine sagte, ich mache mein programm doch nicht langsammer durch ein if was ich nie brauche, selbs wenn ich sowas machen würde

    map<string, foo> m;
    //...
    cin >> von;
    cin >> nach;
    m[nach] = m[von];
    

    fange ich das dann ab mit einen if(von != nach)
    **

    Wenn ich auf die Adressen prüfe, müsste es doch schneller gehen. Aber das geht eben anscheinend bei Mehrfachvererbung nicht immer.

    Original erstellt von Dimah:
    **
    ahja und zu

    class special_class : public some_class, public base_class
    

    kanns du da noch ein bsp ausarbeiten, weil ich das schwer kapierer**

    Beispiel folgt später...



  • Original erstellt von Steven:
    [quote]Original erstellt von Dimah:
    [qb]swap auf buildin kann der compilier so optimieren das er keine temp var braucht

    ...und bei strings und Arrays wird's richtig gemütlich langsam 😞
    [/QB][/QUOTE]
    wenn std::swap auf std::string spezialiesieret ist dan wird std::string::swap() aufgerufen und das tauscht wahrscheinlich ein pointer und zwei longs

    member arrays würde ich mit std::copy machen



  • Mir ist gerade eingefallen, dass durch den swap-Weg mein Problem garnicht gelöst wird, denn auch beim swap'en werden ja mindestens 2 Zuweisungen gemacht:

    template <typename T>              //Beispiel für swap-Funktion
    void swap(const T &O1, const T &O2)
    {
      const T temp(O1);
      O1 = O2;
      O2 = temp;
    }
    

    Wenn O1 und O2 auf das selbe Objekt verweisen, kann es unter Umständen Probleme geben:

    template <typename T>
    class my_list
    {
     //...
     public:
     const my_list &operator =(const my_list &src)
     {
       if(this != &src)   //???
       {
          delete_all();   //erstmal löschen
          add_tail(src);  //src ans Ende anhängen
       }
       return *this;
     }
     //...
    };
    

    Wie muss ich die if-Abfrage machen, damit Zuweisungen immer sicher sind und diese Klasse für Mehrfachvererbung geeignet ist? Ich brauche also einen Weg, um in allen Fällen herauszufinden, dass ein Objekt nicht sich selbst zugewiesen wird.

    [ Dieser Beitrag wurde am 20.04.2003 um 18:44 Uhr von Steven editiert. ]

    [ Dieser Beitrag wurde am 20.04.2003 um 18:45 Uhr von Steven editiert. ]



  • du swapst einfach die member variablen.
    einziges problem ist, wenn du statische arrays hast - aber warum solltest du das haben? (diese kapselt man ja sowieso ein einer eigenen Klasse ala staticArray<class T,int size> - dann sind die kosten gleich, aber niemals mehr als bei deiner methode)

    Beispiel von swap in einer string klasse:

    const String& operator=(String other)
    {
      swap(other);
      return *this;
    }
    
    void String::swap(String& other)
    {
      std::swap(value,other.value);
      std::swap(allocated, other.allocated);
      std::swap(size, other.size);
    }
    

    es wird zum kopieren der Copy Constructor verwendet - das bedeutet keine redunanz.

    ich finde diese möglichkeit ideal -> sie hat keine schwachstelle.



  • Danke, ich glaub' ich check's jetzt. Muss wohl meine tolle Liste umschreiben...
    Trotzdem würde mich mal interessieren, wie man bei Mehrfachvererbung feststellen kann, ob zwei Pointer auf das selbe Teilobjekt zeigen.



  • Hallo,
    meiner Meinung nach ist in der gesamten Diskussion ein Denkfehler.
    Ein this != &re ist IMHO im *Zuweisungsop* einer Klasse immer eindeutig und ok.

    Entweder ich habe in einer Klasse X einen nicht-virtuellen op= mit einem rechtsseitigen Argument vom Typ X, dann sehe ich drei Möglichkeiten:
    1. Zuweisung zwischen Objekten vom Typ X über Referenzen vom Typ X-> Problemlos
    2. Zuweisung zwischen einem Objekt vom Typ X (links) und einem speziellerem Objekt vom Typ Y (rechts).
    In diesem Fall gibt es zwei Möglichkeiten:
    a) Entweder ist die Konvertierung von Y nach X eindeutig, dann gibt es kein Problem mit dem Test this != &re.
    b) oder die Konvertierung ist mehrdeutig (wiederholte und mehrfache Vererbung), dann gibt es keine Zuweisung. Eine Zusweisung ist dann nur über einen expliziten Cast in eine eindeutige Basisklasse möglich -> kein Problem.
    3. Zuweisung zweier Objekte vom Typ X über Basisklassenrefrenzen.
    In diesem Fall gibt es wieder mehrere Möglichkeiten:
    a) Die Zuweisung an die Basisklassenrefrenz ist eindeutig, damit ist dann auch die Zuweisung zwischen den Basisklassenrefrenzen kein Problem.
    b) Die Zuweisung an die Basisklassenreferenzen ist mehrdeutig (Diamant). In diesem Fall wäre das this != &re ein Problem. Ist es aber nicht, da es nicht ohne weitres ausgeführt werden kann. In muss zuvor ja erstmal explizit casten und erhalte damit entweder die Zuweisung zwischen zwei *unterschiedlichen* Basisklassenteilen (des jeweiligen Astes) oder zwischen zwei Basisklassenteilen des selben Asts. Im zweiten Fall verhindert der Test this != &re erfolgreich eine Selbstzuweisung.

    Im Falle, dass es wir mit virtuellen Zuweisungoperatoren arbeiten, kann es schon mal keinen Test this != &re in einer Klasse mit mehrdeutiger Basisklasse geben. Ansonsten sehe ich die Möglichkeiten analog zu oben.

    Mir fällt also keine Situation ein, wo ein Test this != &re im *Zuweisungsoperator* einer Klasse (wo der genaue Typ des linksseitigen Arguments ja bekannt ist) ein Problem wäre.

    Wenn ich einen Fall übersehen haben sollte, nur her damit (und nicht unbedingt mit Scott Meyers kommen, da dieser bereits zugegeben hat, dass er sich in der der einen Ausgabe seines Effective C++ diesbezüglich getäuscht hat: http://cpptips.hyperformix.com/cpptips/multi_addr))



  • Danke!!!!! 🕶 🕶


Anmelden zum Antworten