最安全可靠的是直接用 std::shuffle,需传入带时间种子的随机数引擎(如 std::mt19937(std::random_device{}())),容器须支持随机访问迭代器,且必须包含 和 头文件。

用 std::shuffle 最安全可靠
直接用 std::shuffle,别手写 Fisher-Yates 或调 std::random_shuffle(C++17 已弃用)。它要求传入随机数引擎,否则行为未定义——很多人漏这步,结果每次运行顺序都一样。
常见错误现象:std::shuffle(v.begin(), v.end(), std::default_random_engine()) 看似能跑,但默认构造的引擎种子固定,打乱结果完全可重现。
- 必须显式传一个带时间种子的引擎,比如
std::mt19937(std::random_device{}()) - 容器必须支持随机访问迭代器,
std::vector、std::array、原生数组可以;std::list不行,得先拷贝到 vector 再 shuffle - 若只需伪随机(如测试),可用
std::mt19937(42)固定种子便于复现
std::shuffle 的参数顺序和头文件
顺序容易搞反:std::shuffle(first, last, rng),不是 (rng, first, last)。漏掉 <algorithm></algorithm> 会编译失败;漏掉 <random></random> 则 std::mt19937 找不到。
最小可运行示例:
#include <vector>
#include <algorithm>
#include <random>
#include <iostream>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::mt19937 rng(std::random_device{}());
std::shuffle(v.begin(), v.end(), rng);
// 输出打乱后的 v
}</int></iostream></random></algorithm></vector>
为什么不用 rand() 配 std::random_shuffle
std::random_shuffle 在 C++17 被移除,且旧版用 rand() 有严重缺陷:低比特位周期短、分布不均,尤其在模运算后更明显。即使你用的是 C++14,也该主动避开。
- 用
rand() % n模拟随机索引,n 不是 2 的幂时,结果会有偏差 -
std::mt19937配std::uniform_int_distribution才真正均匀 -
std::shuffle内部已做最优实现,比手写循环更高效、更少出错
对 std::deque 或自定义容器怎么办
std::deque 支持随机访问,std::shuffle 可直接用。但性能不如 vector:内部是分段连续内存,随机跳转有额外开销。
自定义容器只要满足:提供 begin()/end() 返回随机访问迭代器,且迭代器支持 +、-、+= 等操作,就能用 std::shuffle。否则得先转成 vector,shuffle 完再赋值回去——注意移动语义是否生效,避免无谓拷贝。
真正容易被忽略的是:打乱前确认容器非空,否则 begin() == end() 传给 std::shuffle 是合法但无意义的;若逻辑依赖打乱后状态,记得检查 size。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











