std::random_device rd; // Source of seeds!建構函式有一個 string& 型別的引數,它有定義的預設值。在我們像這樣省略它時,會得到我們環境中預設的 random_device 物件。理論上,引數允許我們提供一個字串來標識使用的非確定性資料來源,但需要檢查我們的文件,看看我們的 C++ 庫的這個選項是否可用。下面演示如何用 random_device 物件生成一個種子值:
auto my_lst_seed = rd();這裡用從函數物件 rd 得到的初始值生成了 my_lst_seed。下面是一個成功生成連續種子的程式:
// Generating a succession of 8 seeds #include <random> // For random_device class #include <iostream> // For standard streams int main() { std::random_device rd; // A function object for generating seeds for(size_t n {}; n < 8; ++n) std::cout << rd() << " "; std::cout << std::endl; }這段程式碼呼叫 8 次 rd 所表示的函數並輸出它所返回的值。執行上述程式碼兩次,得到了下面兩行輸出:
3638171046 3646201712 2185708196 587272045 1669986587 2512598564 1822700048 3845359386 360481879 3886461477 1775290740 2501731026 161066623 1931751494 751233357 3821236773
可以注意到,兩次執行得到的輸出是完全不同的。除了 operator()(),random_device 類只定義了其他的 3 個成員函數。成員函數 min() 和 max() 分別返回的是輸出的最小和最大可能值。如果是用亂數引擎而不是非確定性資料來源實現的,成員函數 entropy() 返回的是將資料來源看作 double 或 0 後的熵的估計值。std::seed_seq seeds1; // Default object std::seed_seq seeds2 {2, 3, 4, 5}; // Create from simple integers std::vector<unsigned int> data {25, 36, 47, 58}; // A vector of integers std::seed_seq seeds3 {std::begin(data), std::end(data)}; // Create from a range of integers當然,也可以用 random_device 物件返回的值作為 seed_seq 建構函式的引數:
std::random_device rd {}; std::seed_seq seeds4 {rd(), rd()}; // Create from non-deterministic integers每次執行這段程式碼,seed4 物件都會生成不同的值。
std::vector<unsigned int> numbers (10); // Stores 10 integers seeds4.generate(std::begin(numbers), std::end(numbers));呼叫 seeds4 的成員函數 generate() 可以儲存 numbers 陣列中被生成的值。通過一個範例,我們可以看到 seed_seq 物件在不同條件下生成的值的種類:
// Values generated by seed_seq objects #include <random> // For seed_seq, random_device #include <iostream> // For standard streams #include <iterator> // For iterators #include <string> // For string class using std::string; // Generates and list integers from a seed_seq object void gen_and_list(const std::seed_seq& ss, const string title = "Values:", size_t count = 8) { std::vector<unsigned int> values(count); ss.generate(std::begin(values), std::end(values)); std::cout << title << std::endl; std::copy(std::begin(values), std::end(values), std::ostream_iterator<unsigned int>{std::cout, " "}); std::cout << std::endl; } int main() { std::random_device rd {}; // Non-deterministic source - we hope! std::seed_seq seeds1; // Default constructor std::seed_seq seeds2 {3, 4, 5}; // From consecutive integers std::seed_seq seeds3 {rd(), rd()}; std::vector<unsigned int> data {25, 36, 47, 58}; std::seed_seq seeds4(std::begin(data), std::end(data)); // From a range gen_and_list(seeds1, "seeds1"); gen_and_list(seeds1, "seeds1 again"); gen_and_list(seeds1, "seeds1 again", 12); gen_and_list(seeds2, "seeds2"); gen_and_list(seeds3, "seeds3"); gen_and_list(seeds3, "seeds3 again"); gen_and_list(seeds4, "seeds4"); gen_and_list(seeds4, "seeds4 again"); gen_and_list(seeds4, "seeds4 yet again", 12); gen_and_list(seeds4, "seeds4 for the last time", 6); }gen_and_list() 是一個用來從 seed_seq 物件生成給定個數的值的輔助函數,並且按照標識標題輸出它們。在 main() 中展示了以不同的方式生成的 Seed_seq 物件所生成的值(讀者可自行複製程式碼檢視執行結果)。
std::seed_seq seeds {3, 4, 5}; std::vector<unsigned int> data(seeds.size()); // Element for each seed value seeds.param(std::begin(data)); // Stores 3 4 5 in data這裡會用 seeds 物件的成員函數 size() 返回的值來確定生成的 vector 中元素的個數。seeds 的成員函數 param() 會將傳給建構函式的 3 個值儲存到 data 中。也可以按如下方式將這些值新增到容器中:
seeds.param(std::back_inserter(data)); // Appends 3 4 5 to data當然,不需要儲存這些值——可以傳入一個輸出流疊代器作為 param() 的引數:
seeds.param (std::ostream_iterator<unsigned int>{std::cout," "}); // 3 4 5 to cout