(1)代码来自 qrandom.h ,结合官方的注释:
#ifndef QRANDOM_H
#define QRANDOM_H
#include <QtCore/qalgorithms.h>
#include <algorithm> // for std::generate
#include <random> // for std::mt19937
#ifdef min
# undef min
#endif
#ifdef max
# undef max
#endif
QT_BEGIN_NAMESPACE //说明本类直接定义在 QT 的命名空间
class QRandomGenerator //Note: All functions in this class are reentrant.
{
// restrict the template parameters to
// unsigned integers 32 bits wide or larger
// 为 true 时要求模板参数 UINT 在 32bit 以上
template <typename UInt> //定义模板变量,本值是布尔量
using IfValidUInt = typename std::enable_if<
std::is_unsigned<UInt>::value &&
sizeof(UInt) >= sizeof(uint), bool>::type;
private: //私有部分会包含重要的数据成员的定义
//typedef QIntegerForSizeof<void *>::Signed qptrdiff;
Q_CORE_EXPORT quint64 _fillRange(void *buffer, qptrdiff count);
//应该是从 buffer 地址开始填充 count 个随机数
struct InitialRandomData { //本类用作下面的友元函数的返回值类型
//typedef QIntegerForSizeof<void *>::Unsigned quintptr;
quintptr data[16 / sizeof(quintptr)]; //sizeof(quintptr) = 8
};
friend InitialRandomData qt_initial_random_value() noexcept; //友元函数
friend class QRandomGenerator64 ; //友元类
struct SystemGenerator ; //类声明
struct SystemAndGlobalGenerators;
using RandomEngine = std::mersenne_twister_engine< //模板别名
quint32, 32,624,397,31,0x9908b0df,11,0xffffffff,7,
0x9d2c5680,15,0xefc60000,18,1812433253>;
union Storage //定义了类中类
{
uint dummy ; //本类的数据成员
#ifdef Q_COMPILER_UNRESTRICTED_UNIONS //if分支有效
RandomEngine twister; //本类的成员变量
RandomEngine & engine() { return twister; }
const RandomEngine & engine() const { return twister; }
#else //else分支作废
std::aligned_storage<sizeof(RandomEngine), alignof(RandomEngine)>::type buffer;
RandomEngine &engine() { return reinterpret_cast<RandomEngine &>(buffer); }
const RandomEngine &engine() const { return reinterpret_cast<const RandomEngine &>(buffer); }
#endif
static_assert(std::is_trivially_destructible<RandomEngine>::value,
"std::mersenne_twister not trivially平凡地 destructible as expected");
constexpr Storage(); //本类的默认构造函数
};
Storage storage; //本随机类的数据成员
uint type ; //又一个数据成员
public:
//Initializes this QRandomGenerator object with the value seedValue
//as the seed. Two objects constructed or reseeded with the same seed value
//will produce the same number sequence.
QRandomGenerator(quint32 seedValue = 1) //本类的有参构造函数
: QRandomGenerator(&seedValue, 1) {} //带默认参数,也可以作为无参构造函数
//Initializes this QRandomGenerator object
//with the values found in the array seedBuffer as the seed.
//Two objects constructed or reseeded with the same seed value
//will produce the same number sequence.
//可以这么用: uint t[3]={1,2,3}; //此处必须是无符号数组, int 数组会报错
// QRandomGenerator ma(t);
template <qsizetype N> //普通类型的模板参数,必须给值的
QRandomGenerator(const quint32 (&seedBuffer)[N]) //形参是整型数组
: QRandomGenerator(seedBuffer, seedBuffer + N) {}
//Initializes this QRandomGenerator object
//with len values found in the array seedBuffer as the seed.
QRandomGenerator(const quint32 * seedBuffer, qsizetype len)
: QRandomGenerator(seedBuffer, seedBuffer + len) {}
Q_CORE_EXPORT QRandomGenerator(std::seed_seq & sseq) noexcept;//构造函数
//Initializes this QRandomGenerator object
//with the values found in the range from begin to end as the seed.
Q_CORE_EXPORT QRandomGenerator(const quint32 *begin, const quint32 *end);
//本类的静态成员函数,返回一个指针,指向随机数生成器对象。英文注释讲解略
//返回一个指向共享ORandomGenerator的指针,
//该共享ORandomGenerator总是使用操作系统提供的工具来生成随机数。
//系统设施在至少以下操作系统上被认为是加密安全的:苹果操作系统(Darwin)、BSD、
//Linux、Windows。在其他操作系统上也可能出现这种情况。
//他们也可能支持一个真正的硬件随机数发生器。
//因此,此函数返回的ORandomGenerator不应用于批量数据生成。
//相反,可以用它从<random>头部种子化ORandomGenerator或一个随机引擎。
//此函数返回的对象是线程安全的,可以在任何线程中使用,无需锁定。
//它也可以被复制,生成的 ORandomGenerator也会访问操作系统设施,但它们不会生成相同的序列。
static inline Q_DECL_CONST_FUNCTION QRandomGenerator * system();
//老师说不要用这个函数大量生成随机数据,只用来生成种子即可。!!!!++++
//返回一个共享的QRandomGenerator的指针,该指针使用securelySeeded()进行初始化。
//此函数应用于创建随机数据,
//而无需为特定用途创建昂贵的securely-seeded ORandomGenerator
//或存储较大的 QRandomGenerator对象。
//对这个对象的访问是线程安全的,因此可以在任何线程中使用,无需锁定。
//该对象也可以被复制,而复制产生的序列将与共享对象产生的序列相同。
//但是,请注意,如果有其他线程访问全局对象,这些线程可能会在不可预测的间隔内获取样本。
static inline Q_DECL_CONST_FUNCTION QRandomGenerator * global();//返回指针
//老师说,一般情况用这个静态函数就足够了。!!!!!++++++
//返回一个新的 QRandomGenerator 对象,该对象通过 QRandomGenerator:system()
//安全地进行了初始化。此函数将为 ORandomGenerator 使用的算法获取理想的种子大小,
//因此是创建将保留-段时间的新 ORandomGenerator 对象的推荐方法。
//考虑到安全启动确定性引擎所需的数据量,这个函数有些昂贵,
//不应用于QRandomGenerator 的短期使用
//(使用它生成少于 2600 字节的随机数据实际上是一种资源浪费)。
//如果使用不需要那么多数据,可以考虑使用 ORandomGenerator::global()
//而不是存储一个 ORandomGenerator 对象。
static inline QRandomGenerator securelySeeded(); //返回生成器对象
// copy constructor & assignment operator (move unnecessary)
Q_CORE_EXPORT QRandomGenerator(const QRandomGenerator &other);
//copy 构造函数与 copy 赋值运算符函数
Q_CORE_EXPORT QRandomGenerator & operator=(const QRandomGenerator & other);
friend Q_CORE_EXPORT bool //声明了全局友元函数
operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2);
friend bool operator!=(const QRandomGenerator &rng1,
const QRandomGenerator &rng2 )
{
return !(rng1 == rng2);
}
//Generates a 32-bit random quantity数量 and returns it.
//调用了本类的私有成员函数 _fillRange()以实现本函的功能
quint32 generate() { return quint32(_fillRange(nullptr, 1)); }
//Generates a 64-bit random quantity and returns it.
quint64 generate64()
{
return _fillRange(nullptr, sizeof(quint64) / sizeof(quint32));
}
//Generates one random qreal in the canonical range [0, 1)
//(that is, inclusive of zero and exclusive of 1).
double generateDouble()
{
// IEEE 754 double precision has: 双精度数值,共 64 bit 8字节
// 1 bit sign
// 10 bits exponent 指数部分
// 53 bits mantissa 有效数字
// In order for our result to be normalized in the range [0, 1), we
// need exactly 53 bits of random data. Use generate64() to get enough.
quint64 x = generate64();
quint64 limit = Q_UINT64_C(1) << std::numeric_limits<double>::digits;
x >>= std::numeric_limits<quint64>::digits - //这是个减法运算
std::numeric_limits<double> ::digits ;
return double(x) / double(limit);
}
//Generates 32-bit quantities and stores them
//in the range between begin and end.
// API like std::seed_seq
template <typename ForwardIterator>
void generate(ForwardIterator begin, ForwardIterator end)
{
std::generate(begin, end, [this]() { return generate(); });
}
void generate(quint32 *begin, quint32 *end)
{
_fillRange(begin, end - begin);
}
//generate 与 bound 差不多,前者的取值不受限制,后者有突出边界上限的意思。
//Generates one random double in the range between 0 (inclusive) and
//highest (exclusive).
//This function is equivalent to and is implemented as:
// return generateDouble() * highest; 此行是本函数的实现原理
//If the highest parameter is negative,
//the result will be negative too;
//if it is infinite or NaN,
//the result will be infinite or NaN too (that is, not random).
double bounded(double highest) //形参是 double 类型
{
return generateDouble() * highest;
}
//typedef unsigned int quint32;
quint32 bounded(quint32 highest) //形参是 32 位无符号整数
{
quint64 value = generate();
value *= highest; //先乘法后除法才不会损失精度
value /= (max)() + quint64(1);
return quint32(value);
}
//Generates one random 32-bit quantity in the range between 0 (inclusive)
//and highest (exclusive). highest must be positive.
int bounded(int highest) //函数重载
{
Q_ASSERT(highest > 0);
return int(bounded(0U, quint32(highest)));
}
qint64 bounded(qint64 highest) //形参的无符号与有符号版本
{
Q_ASSERT(highest > 0);
return qint64(bounded(quint64(0), quint64(highest)));
}
quint64 bounded(quint64 highest);
//Generates one random 32-bit quantity in the range between
//lowest (inclusive) and highest (exclusive).
//The highest parameter must be greater than lowest.
quint32 bounded(quint32 lowest, quint32 highest)
{
Q_ASSERT(highest > lowest);
return bounded(highest - lowest) + lowest;
}
int bounded(int lowest, int highest)
{
return bounded(highest - lowest) + lowest;
}
quint64 bounded(quint64 lowest, quint64 highest)
{
Q_ASSERT(highest > lowest);
return bounded(highest - lowest) + lowest;
}
qint64 bounded(qint64 lowest, qint64 highest)
{
return bounded(highest - lowest) + lowest;
}
// these functions here only to help with ambiguous overloads
qint64 bounded(int lowest, qint64 highest)
{
return bounded(qint64(lowest), qint64(highest));
}
qint64 bounded(qint64 lowest, int highest)
{
return bounded(qint64(lowest), qint64(highest));
}
quint64 bounded(unsigned lowest, quint64 highest)
{
return bounded(quint64(lowest), quint64(highest));
}
quint64 bounded(quint64 lowest, unsigned highest)
{
return bounded(quint64(lowest), quint64(highest));
}
//Generates count 32- or 64-bit quantities (depending on the type UInt)
//and stores them in the buffer pointed by buffer.
//This is the most efficient way to obtain more than one quantity at a time,
//as it reduces the number of calls into the Random Number Generator source.
template <typename UInt, IfValidUInt<UInt> = true>
void fillRange(UInt * buffer, qsizetype count)
{
_fillRange(buffer, count * sizeof(UInt) / sizeof(quint32));
}
//Generates N 32- or 64-bit quantities (depending on the type UInt)
//and stores them in the buffer array.
template <typename UInt, size_t N, IfValidUInt<UInt> = true>
void fillRange(UInt (&buffer)[N]) //形参是数组名的类型,N由模板参数确定了
{
_fillRange(buffer, N * sizeof(UInt) / sizeof(quint32));
}
// API like std:: random engines
typedef quint32 result_type; //重载了括号 () 运算符,使本类成为了可调用对象
result_type operator()() { return generate(); }
//Reseeds this object using the value seed as the seed.
void seed(quint32 s = 1) { *this = { s }; }
void seed(std::seed_seq & sseq) noexcept { *this = { sseq }; }
//Discards the next z entries from the sequence.
//This method is equivalent to calling generate() z times
//and discarding the result, 形参是丢掉 z 个随机数
Q_CORE_EXPORT void discard(unsigned long long z);
//Returns the minimum value that QRandomGenerator may ever generate.
//That is, 0.
static constexpr result_type min()
{ return std::numeric_limits<result_type>::min(); }
//Returns the maximum value that QRandomGenerator may ever generate.
//That is, std::numeric_limits<result_type>::max().
static constexpr result_type max()
{ return std::numeric_limits<result_type>::max(); }
protected:
enum System {}; //本类的 protected 属性的成员函数
QRandomGenerator(System); //这是一个构造函数
};
class QRandomGenerator64 : public QRandomGenerator //子类的 64 bit 生成器
{
QRandomGenerator64(System);
public:
// unshadow generate() overloads, since we'll override.
using QRandomGenerator::generate;
quint64 generate() { return generate64(); }
typedef quint64 result_type;
result_type operator()() { return generate64(); }
#ifndef Q_QDOC
QRandomGenerator64(quint32 seedValue = 1)
: QRandomGenerator(seedValue) {}
template <qsizetype N>
QRandomGenerator64(const quint32 (&seedBuffer)[N])
: QRandomGenerator(seedBuffer) {}
QRandomGenerator64(const quint32 *seedBuffer, qsizetype len)
: QRandomGenerator(seedBuffer, len) {}
QRandomGenerator64(std::seed_seq &sseq) noexcept
: QRandomGenerator(sseq) {}
QRandomGenerator64(const quint32 *begin, const quint32 *end)
: QRandomGenerator(begin, end) {}
QRandomGenerator64(const QRandomGenerator &other)
: QRandomGenerator(other) {}
void discard(unsigned long long z)
{
Q_ASSERT_X(z * 2 > z, "QRandomGenerator64::discard",
"Overflow. Are you sure you want to skip over 9 quintillion samples?");
QRandomGenerator::discard(z * 2);
}
static constexpr result_type min()
{ return std::numeric_limits<result_type>::min(); }
static constexpr result_type max()
{ return std::numeric_limits<result_type>::max(); }
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *system();
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *global();
static Q_CORE_EXPORT QRandomGenerator64 securelySeeded();
#endif // Q_QDOC
};
inline quint64 QRandomGenerator::bounded(quint64 highest)
{
// Implement an algorithm similar to libc++'s uniform_int_distribution:
// loop around getting a random number, mask off any bits that "highest"
// will never need, then check if it's higher than "highest". The number of
// times the loop will run is unbounded but the probability of terminating
// is better than 1/2 on each iteration. Therefore, the average loop count
// should be less than 2.
const int width = qCountLeadingZeroBits(highest - 1);
const quint64 mask = (quint64(1) << (std::numeric_limits<quint64>::digits - width)) - 1;
quint64 v;
do {
v = generate64() & mask;
} while (v >= highest);
return v;
}
inline QRandomGenerator * QRandomGenerator::system()
{ //本函利用系统资源生成随机数生成器
return QRandomGenerator64::system();
}
inline QRandomGenerator * QRandomGenerator::global()
{
return QRandomGenerator64::global();
}
//由这里可见,子类的 64 bit的随机数生成器更重要,更基础。
QRandomGenerator QRandomGenerator::securelySeeded()
{
return QRandomGenerator64::securelySeeded();
}
QT_END_NAMESPACE
#endif // QRANDOM_H
(2)
谢谢