Wie teilt Vectoren sauber



  • Alles keine Dinge, die Pointer + new haben.

    Wobei das letzte Argument mit dieser Begründung keinen Sinn macht - schließlich kannst du alle anderen Allokatoren auch so benutzen.



  • Asche auf mein Haupt ich weiß natürlich das new und delete zusammen gehören. Die Zeit wo ich malloc/free brauchte liegt weit in der Vergangenheit. Mea culpa 🙂 .



  • Sone schrieb:

    Alles keine Dinge, die Pointer + new haben.

    Wobei das letzte Argument mit dieser Begründung keinen Sinn macht - schließlich kannst du alle anderen Allokatoren auch so benutzen.

    Ja, aber mit new muss man erst allocate() und dann construct() aufrufen, bei vector lediglich ein Templateargument ändern.



  • dot schrieb:

    andreasgeorg schrieb:

    [...] lohnt es sich überhaubt die Kontainer nutzen zu wollen?

    Wie kümmerst du dich im Moment um die Speicherverwaltung? Exception Safety? Wie stellst du im Moment sicher, dass kein möglicher Ausführungspfad leaked?

    Nun die Speicherverwaltung ist recht simpel. Nach dem Einlesen der Inputdatei Speicher anfordern, wenn ich ihn nicht bekomme war es das -> Fehlermeldung. Sonst rechnen, Daten schreiben, dann Speicher freigeben mit delete.

    Speicherleaks sind dadurch kaum möglich das nur einmal Speicher angefordert wird bevor die Rechenthreads gestartet werden.

    Exception Safety - Kopf einziehen.



  • andreasgeorg schrieb:

    Da die Änderung aber nur ein new und ein free ersetzt, lohnt es sich überhaubt die Kontainer nutzen zu wollen?

    So, wie ich dich verstanden habe, handelt es sich um eine globale Variable, die zum Programmstart initialisiert wird und eigentlich nie freigeben werden muss. Der einzige Gewinn liegt dann darin, dass das Feld komplett mit 0 initialisiert wird.
    Bei globalen Variablen solte man sich immer fragen, ob es sinnvoll und notwendig ist. Im Regelfall lautet die Antwort "Nein".



  • andreasgeorg schrieb:

    Sonst rechnen, Daten schreiben, dann Speicher freigeben mit delete.

    Und beim Rechnen und Daten Schreiben kann nirgendwo was schiefgehen?



  • Mal ein Beispiel was man machen könnte. Die Rangechecks gehen nicht kostenlos, deswegen kann man die auskommentieren.

    #define DEBUG //kommentier mich aus damits schneller geht
    //unter VS lieber _DEBUG benutzen, das wird automatisch definiert
    //beim gcc NDEBUG definieren, damit die asserts weg gehen
    
    struct SubVector{
    #ifdef DEBUG
    	static SubVector create(vector<double> &v, size_t start, size_t size){
    		return SubVector(v, start, size);
    	}
    	static const SubVector create(const vector<double> &v, size_t start, size_t size){
    		return SubVector(const_cast<vector<double> &>(v), start, size);
    	}
    #else
    	static SubVector create(vector<double> &v, size_t start){
    		return SubVector(v, start);
    	}
    	static const SubVector create(const vector<double> &v, size_t start){
    		return SubVector(const_cast<vector<double> &>(v), start);
    	}
    #endif
    	double &operator [](size_t index){
    		assert(index < size);
    		return data[size];
    	}
    private:
    #ifdef DEBUG
    	SubVector(vector<double> &v, size_t start, size_t size_) : size(size_){
    		assert(v.size() > start + size); //sonst greifen wir daneben
    		data = &v[start];
    	}
    #else
    	SubVector(vector<double> &v, size_t start){
    		data = &v[start];
    	}
    #endif
    	double *data;
    #ifdef DEBUG
    	size_t size;
    #endif
    };
    

    Die vielen #ifdefs nerven und dass C++ sowas nicht unterstützt auch:

    SubVector(const vector<double> &v, size_t start) : data(&v[start]) const{
    }
    

    Im Endeffekt kannst du deine double * durch SubVector ersetzen und hast im Debugmode Range-Checks drin. Im Release tut der SubVector dann dasselbe wie der double *.

    Ob das jetzt sauberer ist... naja entscheide selbst.



  • @npw3:

    Es ist völlig redundant, die Funktionsdefinition zweimal stehen zu haben, wenn nur ein kleiner Teil davon je nach Makro unterschiedlich ist.
    Also die PP-Direktiven in den Funktionsrumpf auslagern.

    SubVector(const vector<double> &v, size_t start) : data(&v[start]) const{
    }
    

    Dieser Code macht keinen Sinn. Vor der Konstruktion eines Objektes ist seine Konstanz unwichtig, sonst kämen wir ja zu dem Dilemma das wir es nicht initialisieren könnten (weil es schon im Konstruktor nicht veränderbar ist).

    Außerdem hast du den (mMn. nötigen) Konvertierungsoperator vergessen, sonst ist das schnöde SubVector semantisch nicht so dasselbe wie ein Zeiger...



  • Nein, bei festen Größen nutzt man std::array. Außer die Größen sind so groß, das der Stack zu klein wird

    Immer deine Pauschalantworten. Was, wenn das Array moveable sein soll? Nein, dafuer werde ich std::Array nicht in einen Smartpointer packen sondern gleich std::vector nehmen.

    #ifdef DEBUG 
    ... code 
    #else 
    ... code
    #endif
    

    Wie ich das hasse. Ausserdem scheinst jemand nicht verstanden zu haben, was assert in Abhaengigkeit vom Debug und Release-Modus macht.



  • Danke an Alle,

    ich habe einige Denkanstöße bekommen.


Anmelden zum Antworten