Linker Fehler bei Klasse ähnlich zu Singleton



  • Hey, ich versuche gerade eine Klasse zu schreiben, die die C++11 random-Funktionen kapselt. Da man für den Aufruf der Funktion immer wieder einen "Generator" braucht, dachte ich es ist am performantesten wenn ich diesen in einer Art Singleton-Klasse ablege.

    Frage1: Warum

    Header

    /*
     * CRandom.h
     *
     *  Created on: 06.02.2018
     *      Author: 
     */
    
    #ifndef CRANDOM_H_
    #define CRANDOM_H_
    #include <random>
    
    class CRandom {
    public:
    	static int getRandomInt(int min, int max);
    	static bool evaluateProb(double prob);
    protected:
    	CRandom();
    private:
    	static void createInst();
    	static CRandom *inst;
    	std::default_random_engine generator;
    };
    
    #endif /* CRANDOM_H_ */
    

    Methoden:

    /*
     * CRandom.cpp
     *
     *  Created on: 06.02.2018
     *      Author: 
     */
    
    #include "CRandom.h"
    #include <random>
    
    using namespace std;
    
    CRandom *CRandom::inst = 0;
    
    int CRandom::getRandomInt(int min, int max) {
    	uniform_int_distribution<int> distribution(min,max);
    	if (CRandom::inst == 0)
    		createInst();
    
    	return distribution(inst->generator);
    }
    
    bool CRandom::evaluateProb(double prob) {
    	bernoulli_distribution distribution(prob);
    
    	if (CRandom::inst == 0)
    		createInst();
    
    	return distribution(inst->generator);
    }
    
    //WARNING! This method creates a new instance regardless of the content of inst. so check before if its zero
    void CRandom::createInst() {
    	inst = new CRandom();
    }
    

    Linker output:

    Building target: myProg
    Invoking: Cross G++ Linker
    g++  -o "myProg"  ./CGenerateInput.o ./CRandom.o ./CSVParser.o ./CSimulate.o ./ConfigTable.o ./RapidFireTable.o ./Unit.o ./main.o   
    ./CRandom.o: In Funktion `CRandom::createInst()':
    /home/ich/Programmierung/eclipse-workspace/myProg/Debug/../CRandom.cpp:34: Nicht definierter Verweis auf `CRandom::CRandom()'
    makefile:44: die Regel für Ziel „myProg“ scheiterte
    collect2: error: ld returned 1 exit status
    make: *** [myProg] Fehler 1
    

    Frage1: Warum findet der Linker den Konstruktor nicht? Der müsste doch eigentlich automatisch generiert werden.

    Frage2: Ist das überhaupt notwendig? Gibt es da bessere Lösungen? Ich möchte einfach nur möglichst performant aus allen src-Dateien auf die Random-Funktionen zugreifen können.
    Grüße



  • Versuch mal

    CRandom()=default;
    


  • __self schrieb:

    Frage1: Warum findet der Linker den Konstruktor nicht? Der müsste doch eigentlich automatisch generiert werden.

    class CRandom {
    ...
    protected:
        CRandom();
    ...
    };
    

    Du behauptest, dass du ihn implementierst.

    __self schrieb:

    Frage2: Ist das überhaupt notwendig? Gibt es da bessere Lösungen?

    Nein. Ich sehe nicht, warum du überhaupt ein Klasse benötigst.

    namespace MyRandom {
        int getRandomInt(int min, int max);
        bool evaluateProb(double prob);
    }
    

    sollte ausreichen.



  • Ich weiß nicht, finde diese selbstgebauten Wrapper um Random nie gut. Ich habe schon mehrere davon irgendwo gefunden und denke immer "was soll das?".

    Du hast gesagt, dir geht es um Performance. Ich denke, du solltest in diesem Fall eine RNG-Engine pro Thread haben. Also würde ich sagen, mach einen

    thread_local std::mt19937 generator;
    

    und verzichte ansonsten auf deine komplette Klasse.

    bernoulli_distribution() finde ich auch klarer als evaluateProb.



  • wob schrieb:

    Du hast gesagt, dir geht es um Performance. Ich denke, du solltest in diesem Fall eine RNG-Engine pro Thread haben. Also würde ich sagen, mach einen

    thread_local std::mt19937 generator;
    

    und verzichte ansonsten auf deine komplette Klasse.

    Hey danke, das klappt sehr gut. Den Seed stelle ich momentan in der main.cpp ein. Das ist an sich kein großes Problem, da es sich um ein überschaubares Projekt handelt, aber wie würde man sowas bei größeren lösen?


Anmelden zum Antworten