0

I'm trying to write a code where I create an object mt19937 in a class A that can be used in the class internal functions for generating random numbers and I also want to pass a reference to this same object to various instances of the class B declared inside of the class A. Those objects passed through reference should be able to also generate random numbers for internal use in the class B.

The problem is: in the class A it generates random numbers, but the class B it generates the same sequences.

I have a code separated in three files like the example:

Class A

A.h:

#include <random>
#include <vector>
#include "B.h"

using namespace std;

class A
{
    public:
        A();
    private:
        mt19937 mt;
};

A.cpp:

#include "A.h"

A::A() : mt((random_device())())
{
    vector<B> Bs;

    for(int i = 0; i < 10; i++)
    {
        Bs.emplace_back(i, mt);
    }
}


Class B

B.h:

#include <random>
#include <iostream>

using namespace std;

class B
{
    public:
        B(int id, mt19937& mt);
    private:
        int id;
        mt19937 mt;
};

B.cpp:

#include "B.h"

B::B(int id, mt19937& mt)
{
    this->id = id;
    this->mt = mt;

    bernoulli_distribution dist(0.5);
    cout << "Testing random..." << endl;
    for(int i = 0; i < 10; i++)
    {
        cout << dist(this->mt) << " ";
    }
    cout << endl;
}

main

main.cpp:

#include "A.h"

int main()
{
    A a;
    return 0;
}

I don't know if it can help, but I'm compiling it like this:

g++-12 B.cpp A.cpp main.cpp -o main -std=c++17

and my computer is a Macbook Pro M1 running a Mac OS Monterey 12.2.1

I tried generating a random sequence of numbers for each instance of B, but each instance is getting the same sequence.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 9
    you _pass_ it by reference but then store it by value. – tkausl Dec 16 '22 at 23:40
  • This code doesn't generate anything, since the `main` function only contains a function declaration and a `return 0;` – UnholySheep Dec 16 '22 at 23:41
  • @tkausl could you give me a simple example of how to do it? I'm a little confused.. :/ – Bryan Barbosa Dec 16 '22 at 23:46
  • 1
    `class B { /*..*/private: int id; mt19937& mt; }`. – Jarod42 Dec 16 '22 at 23:48
  • @Jarod42 but when I modify the line on B.h to mt19937& mt;, I get this when compiling: " error: uninitialized reference member in 'std::mt19937&'", and I don't want to create a new object, I simply want to create a reference to the object created in A – Bryan Barbosa Dec 16 '22 at 23:59
  • @BryanBarbosa Yes, you need to _initialize_ the reference rather than _assigning_ to it like you're doing. Use the initialization list like you did in `A`. – Miles Budnek Dec 17 '22 at 01:12
  • *" I don't want to create a new object, I simply want to create a reference to the object created in A"* -- to paraphrase, you don't want `mt19937 mt;` in `B`, you simply want `mt19937& mt;` initialized to the object created in `A`. The compiler error is telling you that your code does not do what you want it to do. – JaMiT Dec 17 '22 at 01:56
  • A simpler solution might be to just use two independent, randomly initialised generators rather than trying to share them – Alan Birtles Dec 17 '22 at 07:11

1 Answers1

0

You are passing a reference but storing it as an object, hence you are constructing a new "mt" to solve this (with references) you need to make the following changes in B.h:

#include <random>
#include <iostream>

using namespace std;

class B
{
    public:
        B(int id, mt19937& mt);
    private:
        int id;
        mt19937 &mt; //<--- we need a reference
};

Now in B.cpp you need to initialize the reference with a member initializer list:

#include "B.h"

B::B(int id, mt19937& mt) : mt(mt) // <-- initializer list
{
    this->id = id;
    // this->mt = mt; <-- we don't need this

    bernoulli_distribution dist(0.5);
    cout << "Testing random..." << endl;
    for(int i = 0; i < 10; i++)
    {
        cout << dist(this->mt) << " ";
    }
    cout << endl;
}

Hope it helps!

Milan Š.
  • 1,353
  • 1
  • 2
  • 11