Vektorenaddition



  • curry schrieb:

    nein, leider erzeugt das addieren und multiplizieren müll in der Rückgabe, weil es wie gesagt den Speicher per Destruktoraufruf frei gibt. Was benutzt du für einen Compiler? Vielleicht erklärt das auch, dass er bei dir durchläuft.

    Great thanxxx for answers
    Curry

    g++. Aber wie du bereits selbst geschrieben hast, fehlt der Copy-Ctor. Dieser sollte etwa so aussehen:

    Vector::Vector(const Vector& vec)
    {
          n_ = vec.n_
          elemente_ = new double[n_];
          for(unsigned int i = 0; i < n_; ++i)
                  elemente_[i] = vec.elemente_[i];
    }
    

    Caipi



  • Vector::Vector(const Vector& copyVector):elemente_(NULL),n_(copyVector.groesse()){
    		elemente_ = new double[groesse()];
            for (int i = 0; i < groesse(); ++i)
                elemente_[i] = copyVector.elemente_[i];
    	};
    

    das hier hatte mir noch gefehlt Caipi, jetzt funzts.
    Jetzt kann ich auch befriedigt ins Bett gehen. Noch eine kurze Frage an dich: Was studerst du und hast du ICQ? Für den Fall, dass man mal noch andere Fragen haben sollge.



  • curry schrieb:

    Vector::Vector(const Vector& copyVector):elemente_(NULL),n_(copyVector.groesse()){
    		elemente_ = new double[groesse()];
            for (int i = 0; i < groesse(); ++i)
                elemente_[i] = copyVector.elemente_[i];
    	};
    

    So in der Art wie ich geschrieben hab ;). Trotzdem eine Frage dazu: Warum setzt du den Zeiger elemente_ auf Null, wenn du ihm direkt danach eine Adresse zuweist?

    das hier hatte mir noch gefehlt Caipi, jetzt funzts.
    Jetzt kann ich auch befriedigt ins Bett gehen. Noch eine kurze Frage an dich: Was studerst du und hast du ICQ? Für den Fall, dass man mal noch andere Fragen haben sollge.

    Ich studiere garnichts. Gehe in die Schule... Desweiteren kannst du doch deine Fragen hier stellen, oder? 😕

    Caipi



  • ich setze ihn aus dem Grund auf NULL, weil stell dir vor dein Programm kommt aus irgend einer fehlerhaften Implementierung ins Rudern und eine Elementzuweisung kommt nicht mehr zustande, wo greift der Destruktort dann hin? Ins Leere, richtig, und dass was er dabei an Daten versehentlich löschen kann, kann zu schweren Fehlern führen.



  • das mit dem Fragen hier stellen, ist immer so eine lässtige angelegenheit mit dem warten auf Antworten. Einige der hier anwesenden halten sich gerne für Überflieger und Posten dementsprechend völlig unzureichende überhebliche Antworten. Daher ist mir's lieb einen Stamm an C++ Usern zu Adden auf den man verlässlich in Problemsituaionen zurückgreifen kann.

    Deswegen der ausweg ins ICQ



  • curry schrieb:

    ich setze ihn aus dem Grund auf NULL, weil stell dir vor dein Programm kommt aus irgend einer fehlerhaften Implementierung ins Rudern und eine Elementzuweisung kommt nicht mehr zustande, wo greift der Destruktort dann hin?

    Wo greift der Dtor denn jetzt hin? 😉

    Ins Leere, richtig,

    So auch jetzt.

    und dass was er dabei an Daten versehentlich löschen kann, kann zu schweren Fehlern führen.

    Stimmt.

    Es ist nicht so, dass wenn du einem Zeiger 0 setzt, nichts mehr schief gehen kann. Im Gegenteil. Wenn du einen Zeiger, der auf 0 zeigt, dereferenzierst, gibt es ziemlich sicher einen Crash, da 0 nie eine gültige Adresse repräsentiert.
    Warum setzt man nun aber den Zeiger gleich 0? Das tut man deswegen, da man vor dem dereferenzieren oder freigeben überprüft ob dieser gleich 0 ist, und sofern diese Bedingung zutrifft man den Speicher _nicht_ dereferenziert oder freigibt...

    Caipi



  • na das klingt doch auch nicht schlecht 🙂 wieder was gelernt.
    Dann mach dir mal noch nen schönen Abend. Wenn du lust hast dich noch bisschen mehr über C++ Relevante Sachen auszutauschen hier meine ICQ addi: 70049002
    in diesem Sinne: N8

    Gruß Curry



  • ● Der Standardkonstruktor beschafft und initialisiert dynamische
    Anteile
    ● Handelt es sich um dynamischen Speicher wird der entsprechende
    Zeiger in der Initialisiererliste mit NULL initialisiert
    ● Der nötige Speicher wird im Konstruktor mit new oder new[] beschafft
    ● Schlägt die Speicherbeschaffung fehl, enthält der Zeiger den Wert NULL
    ● Ein anschließender Destruktoraufruf, der den Zeiger mit delete
    oder delete [] freigibt, bleibt dann ohne negative Folgen
    ● Ein NULL-Zeiger darf beliebig oft freigegeben werden
    ● Dynamischen Speicher keinesfalls in der Initialisiererliste beschaffen!
    ● Im Falle eines Fehlschlags hätte der Zeiger einen Wert ungleich NULL
    ● Ein späterer Destruktoraufruf mit delete oder delete[] hätte dann
    negative Folgen

    So stands im Skriptum, man darf demzufolge einen solchen Zeiger dereferenzieren.

    Gruß Curry



  • curry schrieb:

    ● Schlägt die Speicherbeschaffung fehl, enthält der Zeiger den Wert NULL

    Diese Info ist veraltet.
    Nach aktuellem C++ Standard wird dem Zeiger nicht der Wert 0 zugewiesen sondern eine Exception geworfen...

    So stands im Skriptum, man darf demzufolge einen solchen Zeiger dereferenzieren.

    Dereferenzieren nicht, wenn überhaupt freigeben...
    Vergl.

    #include <iostream>
    using namespace std;
    
    int main()
    {
          int* p = 0;
          cout << *p << endl;
    }
    

    (oder hab ich was überlesen?).

    Jedoch würde mich das mit dem "auf einen Null-Zeiger darf beliebig oft delete angewendet werden" auch mal interessieren. Ist das nach aktuellem Stadard legal?
    Ich habe nämlich dumpf in Erinnerung, dass man nur Speicher der mit new erzeugt wurde wieder freigeben darf und wenn nach aktuellem Standard bei einem Fehlschlag von new der Zeiger nicht gleich null gesetzt wird, dann ist ein Null-Zeiger ja nicht mit new erzeugt, oder? (Sorry, bin Noob :))
    Kann mich da jemand aufklären? :).

    Caipi



  • 5.3.5 Delete [expr.delete]
    1 The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.
    delete-expression:
    ::opt delete cast-expression


    The first alternative is for non-array objects, and the second is for arrays. The operand shall have a pointer
    type, or a class type having a single conversion function (12.3.2) to a pointer type. The result has type
    void.
    2 If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned
    conversion function, and the converted operand is used in place of the original operand for the remainder of
    this section. In either alternative, if the value of the operand of delete is the null pointer the operation
    has no effect. In the first alternative (delete object), the value of the operand of delete shall be a pointer
    to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause
    10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of
    delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the
    behavior is undefined. [Note: this means that the syntax of the delete-expression must match the type of the
    object allocated by new, not the syntax of the new-expression. ] [Note: a pointer to a const type can be
    the operand of a delete-expression; it is not necessary to cast away the constness (5.2.11) of the pointer
    expression before it is used as the operand of the delete-expression. ]
    3 In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the
    static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual
    destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the
    object to be deleted differs from its static type, the behavior is undefined.73)
    4 The cast-expression in a delete-expression shall be evaluated exactly once. If the delete-expression calls
    the implementation deallocation function (3.7.3.2), and if the operand of the delete expression is not the
    null pointer constant, the deallocation function will deallocate the storage referenced by the pointer thus
    rendering the pointer invalid. [Note: the value of a pointer that refers to deallocated storage is indeterminate.]
    5 If the object being deleted has incomplete class type at the point of deletion and the complete class has a
    non-trivial destructor or a deallocation function, the behavior is undefined.
    6 The delete-expression will invoke the destructor (if any) for the object or the elements of the array being
    deleted. In the case of an array, the elements will be destroyed in order of decreasing address (that is, in
    reverse order of the completion of their constructor; see 12.6.2).
    7 The delete-expression will call a deallocation function (3.7.3.2).
    8 [Note: An implementation provides default definitions of the
    global deallocation functions
    operator delete() for non-arrays (18.4.1.1) and operator delete[]() for arrays (18.4.1.2).
    A C + + program can provide alternative definitions of these functions (17.4.3.4), and/or class-specific versions
    (12.5). ] When the keyword delete in a delete-expression is preceded by the unary :: operator, the
    global deallocation function is used to deallocate the storage.
    9 Access and ambiguity control are done for both the deallocation function and th destructor (12.4, 12.5).


Anmelden zum Antworten