2

I draw random numbers using <random> from C++11. I do it by creating an instance obj of the following class (for the interested reader: It is taken from this thread):

class RNG
{
public:
    typedef std::mt19937 Engine;
    typedef std::uniform_real_distribution<double> Distribution;


    double operator()()
    {
        return distribution(engine);
    }
    Engine engine;
    Distribution distribution;
};

Calling obj() gives me the desired random number. Now, I have three functions that all have to use obj. Declaring obj global would work, but is it also correct? Or are there other (more correct) alternatives?

Community
  • 1
  • 1
BillyJean
  • 1,537
  • 1
  • 22
  • 39
  • 5
    A member `static` **is** a global, don't kid yourself. – Luchian Grigore Apr 10 '13 at 14:12
  • 2
    Correctness of globals depends on the rest of the program. I'd pass an RNG to each function that needs one, that makes deterministic tests possible. – Fred Foo Apr 10 '13 at 14:14
  • I just wanted to ask the same. Usually the only difference between global and static (in some programming languages) is that static is not everywhere visible, but both are living all the time. – Amegon Apr 10 '13 at 14:14
  • 1
    All three function could use separate instances of the class. Or use a global variable. If the functions are in the same source file you could make an anonymous (unnamed) namespace containing the instance, or even a global static instance. – Some programmer dude Apr 10 '13 at 14:14
  • If instances produce different random numbers (somehow different seeding or **real** real random numbers) then it would not matter to define multiple objects or just one. The class is small enough to define multiple if it helps to stay loose coupled. Otherwise access one global one. Up to your, which structure feels better – Amegon Apr 10 '13 at 14:17

2 Answers2

2

It depends. If the part of your program that works with RNG consists of and will likely consist of (hard to see the future though) just those three functions, and those functions only need to work on one object - always the same, all the time-, then why not making that object global.

Avoid restricting a type to only have one instance (Singleton pattern) unless that is an inherent characteristic of that type. If your program uses only one instance of RNG, then your program will just create one instance (i.e., make the object global, or constrain your program - not the type - to only create one instance). I can very well imagine that other libraries or programs may create several random generators.

Of course, if one day those functions will have to work on several different instances of RNG (although one at a time), then you will need to let them take an instance of that class as a function argument, and let them work on that argument. Clients will have to take care of providing the appropriate instance of RNG as an argument to those functions.

Then, if one day you will realize that those functions will also end up all working on other object types, and those data are somehow related to each other, you could consider wrapping them in a data structure or in a class, possibly making your functions member functions of that class - if the operation it carries out is fundamental for that type.

Giving guidelines in general without knowing what you have in mind, and what kind of application or library you are going to write, is not easy. Hopefully this helped a bit.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
1

Use singleton pattern.

Just add one method:

 static RNG& inst()
 {
     static RNG instance;
     return instance;
 }

And disable copying of your object:

private:
    RNG(const RNG&); // without implementation
    RNG& operator=(const RNG&); // without implementation

Then you can access to your instance:

d = RNG::inst()();
loentar
  • 5,111
  • 1
  • 24
  • 25
  • 1
    +1 for the easiest and most beautiful design pattern: Singleton. Improves software quality so much. And nice way to use static here instead of a check for null/nothing, since that check adds the requirement to deal with racing problems – Amegon Apr 10 '13 at 14:18
  • 1
    @Amegon Most overused and dangerous pattern trying to hide bad design, you mean? – Bartek Banachewicz Apr 10 '13 at 14:20
  • 2
    Wait, why can't we have more than one random number generator? – R. Martinho Fernandes Apr 10 '13 at 14:22
  • Singletons should only really be used when there is a legitimate reason for why only one instance of the object can exist (Like, maybe a logger? Or a graphics engine interface?) as opposed to compensating for bad design. – SlxS Apr 10 '13 at 14:24
  • Using `static` replaces initialization race problems with order of destruction problems. – Pete Becker Apr 10 '13 at 14:25
  • @ R. Martinho Fernandes, Probably because it should be seeded once and then get next randoms – Abhijit-K Apr 10 '13 at 14:25
  • The entire object is `static` there is no pointer hence the static instance would be properly initialized before first call to `inst()`, so no multi thread issues I think – Abhijit-K Apr 10 '13 at 14:27
  • 1
    @AbhijitKadam I believe there are potential issues with multi-threading using this method: http://stackoverflow.com/questions/3069255/singleton-multi-threading (It is thread-safe in C++11 though, http://stackoverflow.com/questions/1661529/is-meyers-implementation-of-singleton-pattern-thread-safe) – SlxS Apr 10 '13 at 14:31
  • @BartekBanachewicz dangerous design, because people use it like global variables? SlxS, thanks for the explanation. So if it is a large class with much initialization code, then a Singleton would be okay? – Amegon Apr 10 '13 at 14:33
  • @ SlxS In that example the pointer is `static` the object is not. Here the entire object is static and should be initialized before the `main()`. However the object will stay lifetime. – Abhijit-K Apr 10 '13 at 14:33
  • 1
    @Amegon Because it has exactly the same problems global variables have, but it covers them instead of solving them. Singleton has very limited real-world usage. – Bartek Banachewicz Apr 10 '13 at 14:34
  • @BartekBanachewicz If a Singleton is defined inside a class or any custom namespace, doesn't this prevent the biggest risk of global variables? (the risk that another class defines the same name, leading to unexpected results)? – Amegon Apr 10 '13 at 14:36
  • 1
    That's not the biggest risk of global variables. Anyway, it's not about the "risk". It's about bad design. – Bartek Banachewicz Apr 10 '13 at 14:37