2016-06-18 4 views
-2

переменная «инициализирован» в методе initRandomSeed()Могу ли я использовать глобальную переменную вместо статической локальной переменной?

/* 
* File: random.cpp 
* ---------------- 
* This file implements the random.h interface. 
*/ 


#include <cstdlib> 
#include <cmath> 
#include <ctime> 
#include "random.h" 
#include "private/randompatch.h" 
using namespace std; 

/* Private function prototype */ 

static void initRandomSeed(); 

/* 
* Implementation notes: randomInteger 
* ----------------------------------- 
* The code for randomInteger produces the number in four steps: 
* 
* 1. Generate a random real number d in the range [0 .. 1). 
* 2. Scale the number to the range [0 .. N) where N is the number of values. 
* 3. Translate the number so that the range starts at the appropriate value. 
* 4. Convert the result to the next lower integer. 
* 
* The implementation is complicated by the fact that both the expression 
* 
*  RAND_MAX + 1 
* 
* and the expression for the number of values 
* 
*  high - low + 1 
* 
* can overflow the integer range. These calculations must therefore be 
* performed using doubles instead of ints. 
*/ 

int randomInteger(int low, int high) { 
    initRandomSeed(); 
    double d = rand()/(double(RAND_MAX) + 1); 
    double s = d * (double(high) - low + 1); 
    return int(floor(low + s)); 
} 

/* 
* Implementation notes: randomReal 
* -------------------------------- 
* The code for randomReal is similar to that for randomInteger, 
* without the final conversion step. 
*/ 

double randomReal(double low, double high) { 
    initRandomSeed(); 
    double d = rand()/(double(RAND_MAX) + 1); 
    double s = d * (high - low); 
    return low + s; 
} 

/* 
* Implementation notes: randomChance 
* ---------------------------------- 
* The code for randomChance calls randomReal(0, 1) and then checks 
* whether the result is less than the requested probability. 
*/ 

bool randomChance(double p) { 
    initRandomSeed(); 
    return randomReal(0, 1) < p; 
} 

/* 
* Implementation notes: setRandomSeed 
* ----------------------------------- 
* The setRandomSeed function simply forwards its argument to srand. 
* The call to initRandomSeed is required to set the initialized flag. 
*/ 

void setRandomSeed(int seed) { 
    initRandomSeed(); 
    srand(seed); 
} 

/* 
* Implementation notes: initRandomSeed 
* ------------------------------------ 
* The initRandomSeed function declares a static variable that keeps track 
* of whether the seed has been initialized. The first time initRandomSeed 
* is called, initialized is false, so the seed is set to the current time. 
*/ 

static void initRandomSeed() { 
    static bool initialized = false; 
    if (!initialized) { 
     srand(int(time(NULL))); 
     initialized = true; 
    } 
} 

Чтобы убедиться, что код инициализации не получает выполняется каждый время, вам нужен логический флаг для записи того, что инициализация было выполнено. К сожалению, это не работает, чтобы объявить флаг как глобальную переменную, потому что C++ не задает порядок в , какие глобальные переменные инициализируются. Если вы объявляете другие глобальные значения , начальные значения которых были получены в случайной библиотеке , не было бы способа установить правильность установки флага инициализации .

Можете ли вы привести пример: «Если вы объявляете другие глобальные значения, начальные значения которых были получены с помощью случайной библиотеки, то не было бы никакого способа, чтобы гарантировать, что флаг инициализации был установлен правильно.»

+0

вы действительно думаете, что вопрос становится лучше путем удаления каких-либо прямых ссылок на «книги» (все равно было бы неплохо узнать, откуда вы копируете вставные материалы), все еще ссылаясь на полный блок текста? – user463035818

ответ

0

Вы хотите искать статическую инициализацию крах: https://cryptopp.com/wiki/Static_Initialization_Order_Fiasco

Например, если вы должны были объявить глобальный переменный Минт:

Int Минт = initRandomSeed();

это будет получить выполняется перед ваша программа входит в основной() блок, и нет никакой гарантии, что initialized получает набор перед MyInt

Смежные вопросы