Programm stürzt zufällig ab



  • unique_philosoph schrieb:

    Bengo schrieb:

    Problem ist aber, dass ich dann in meiner While Schleife erneut den Konstruktor aufrufen müsste, was ich nicht kann.

    Aber einen Zuweisungsoperator hast du doch?

    fac = Faktor(number);
    

    sollte automatisch gehen.

    Also mein Programm würde dann so aussehen:

    int lastNumber = 0;
        for (int i = 20; i < 91000; ++i) {
            Faktor fac(i);
            int counter = 0;
            while(1) {
                int number = fac.getNextNumber();
                counter ++;
                fac = Faktor(number);
                if (number == lastNumber) {
                    cout << i << ": Geht auf prim " <<counter << endl;
                    lastNumber = number;
                    break;
                }
                lastNumber = number;
                if (number > 100000) {
                    cout << i << ": Zu groß zum Berechnen "<<counter << endl;           
                    break;
                }  
                counter ++;
            }
        }
    

    Den zuweisungsoperator kann ich doch dann so definieren und implementieren lassen?:

    Faktor& operator=(const Faktor&& rhs)=default;
    


  • unique_philosoph schrieb:

    Bengo schrieb:

    Problem ist aber, dass ich dann in meiner While Schleife erneut den Konstruktor aufrufen müsste, was ich nicht kann.

    Aber einen Zuweisungsoperator hast du doch?

    fac = Faktor(number);
    

    sollte automatisch gehen.

    Super! Statt jeden Schleifendurchlauf ein neues Objekt zu erstellen, erstellen wir immer noch jeden Schleifendurchlauf ein Objekt und kopieren dieses noch zusätzlich!



  • sebi707 schrieb:

    unique_philosoph schrieb:

    Wieso, std::vector ist ein perfekter Nutzungszweck für unique_ptr![cpp]

    In deinem Beispiel steht aber noch ein new . Du hättest make_unique benutzen sollen! Aber irgendwo muss am Ende aber auf jeden Fall ein new stehen müssen.

    make_unique ruft den Konstruktor auf und das will ich nicht.

    Was soll eigentlich das ganze aligned_storage Klimbim? Wenn ich new T[N] schreibe ist das ja wohl schon passend aligned für T.

    Ja, aber das ruft den Konstruktor auf (für allgemeine T) und das will ich nicht.

    @Mechanics: Ich wollte es nur klarstellen. In dem Zitat über deinem Post stand was von new/delete.


  • Mod

    Ich werfe mal std::allocator (bzw. Allocators im Allgemeinen) in den Raum. schließlich ist es dieser, der intern von den ganzen Smartpointern und Containern genutzt wird, sofern man ihnen nichts anderes vorgibt. Klar läuft dieser intern letztlich auf so etwas wie aligned_storage und ein placement new hinaus. Aber so lange man nicht tatsächlich einen eigenen Allocator implementiert, wird man immer noch keinen Kontakt mit new/delete haben. Einen eigenen Container zu implementieren reicht als Grund noch nicht aus. Die Aufgabe eines Containers ist das Verwalten seiner Elemente, nicht das Beschaffen von Speicher.



  • Bengo schrieb:

    Den zuweisungsoperator kann ich doch dann so definieren und implementieren lassen?:

    Faktor& operator=(const Faktor&& rhs)=default;
    

    Nein, da hast du jetzt eine konstante RValue Referenz als Parameter drin und das macht nicht wirklich Sinn. Außerdem kriegst du die Operatoren alle schon automatisch, ohne das du die =default setzt.

    Sinnvoller für dich wäre wohl ein operator= , welcher einen int akzeptiert und dann das gleiche macht wie dein Konstruktor (minus eventuell Speicherreservierung). Wie sieht deine Faktor Klasse überhaupt aus? Was für Membervariablen hat die Klasse und was macht dein Konstruktor? Nicht das die Klasse überhaupt nur einen int enthält, denn dann lohnt die ganze Optimierung nicht. Mit diesem operator= könntest du dann sowas schreiben:

    Faktor fac;
    for (int i = 4; i < 1000; ++i) {
        fac = i;
        // [...]
    }
    

    unique_philosoph schrieb:

    Ja, aber das ruft den Konstruktor auf (für allgemeine T) und das will ich nicht.

    OK, seh ich ein.



  • So?

    class Faktor {
    public:
        Faktor(int number);
        ~Faktor();
        int getNextNumber(void);
        Faktor& operator=(int number);
    private:
        Faktor(const Faktor& orig);
        void setPrime(const int prime,const int expo);
        std::vector<PrimePair> primes;
        Primes p;
        void init(int number);
    };
    
    Faktor::Faktor(int number) {
        init(number);
    }
    
    void Faktor::init(int number) {
        primes.erase(primes.begin(), primes.end());
        int counter = 0;
        int bound = floor(sqrt(number))+1;
        for(auto &i : p.primes) {
            if (i > bound) {
                break;
            }
            while (number % i == 0) {
                number = number / i;
                ++counter;
            }
            if (counter != 0) {
                setPrime(i, counter);
                counter = 0;
            }
        }
    }
    
    Faktor& Faktor::operator =(int number) {
        init(number);
        return *this;
    }
    
    }
    

    Das funktionert nun endlich so wie es soll. Und es ist tatsächlich merklich schneller geworden, obwohl ich dachte der großteil geht für die eigentliche Berechnung drauf.
    Bin auch dumm, hab vorher meine primzahlliste immer wieder neu erstellt.



  • Was macht setPrime ? Du musst bei dem operator= natürlich beachten, dass du den Inhalt diverser vector löscht, falls du damit nichts mehr anfangen kannst. Sowas wie schonmal berechnete Primzahlen kann man natürlich behalten. Du musst nur sehen, dass deine Funktionen mit schon teilweise befüllten Vektoren klar kommen.



  • sebi707 schrieb:

    Nein, da hast du jetzt eine konstante RValue Referenz als Parameter drin und das macht nicht wirklich Sinn. Außerdem kriegst du die Operatoren alle schon automatisch, ohne das du die =default setzt.

    Ja sehe was du meinst, in der Referenz ist es aber möglich http://en.cppreference.com/w/cpp/language/move_operator



  • sebi707 schrieb:

    Was macht setPrime ? Du musst bei dem operator= natürlich beachten, dass du den Inhalt diverser vector löscht, falls du damit nichts mehr anfangen kannst. Sowas wie schonmal berechnete Primzahlen kann man natürlich behalten. Du musst nur sehen, dass deine Funktionen mit schon teilweise befüllten Vektoren klar kommen.

    Set Prime setzt ein Object mir Primzahl und Exponent in den Vector. Hab bei der init Funktion nun noch einen Befehl reingemacht, der den vektor vorher komplett leert.



  • Bengo schrieb:

    Ja sehe was du meinst, in der Referenz ist es aber möglich http://en.cppreference.com/w/cpp/language/move_operator

    Der move Operator ist aber ohne const.

    Bengo schrieb:

    Hab bei der init Funktion nun noch einen Befehl reingemacht, der den vektor vorher komplett leert.

    Es gibt eine clear Funktion beim vector. Ist kürzer zu schreiben und möglicherweise schneller.



  • clear klingt gut, hätte das zweite google ergebnis nehmen sollen 😃

    Noch mal vielen Dank an alle, denke man Code ist nun im 21Jh angekommen 😉


Anmelden zum Antworten