跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C++ random_shuffle随机洗牌 _ 数组乱序打乱算法【实战】

std::random_shuffle在C++17中已被彻底移除,应改用std::shuffle配合std::mt19937等确定性随机引擎,需显式传入随机数生成器对象并注意迭代器范围与种子管理。 random_shuffle 已被 C++17 移除,别再用了 直接说结论:
std::random_shuffle
在 C++17 中已被彻底移除,编译器(如 GCC 9+、Clang 7+)启用
-std=c++17
或更高标准时会报错:
error: 'random_shuffle' is not a member of 'std'
。它早在 C++11 就被标记为 deprecated,原因是依赖全局随机状态(
std::rand
),不可预测、不可重现、线程不安全,且无法指定随机数引擎。 用 shuffle + mt19937 替代 random_shuffle 正确做法是用
std::shuffle
配合高质量随机数引擎,最常用的是
std::mt19937
。关键点不是“换函数”,而是必须显式传入一个可调用的随机数生成器对象:
std::shuffle
第三个参数必须是函数对象(functor)或 lambda,不能是函数指针或裸
std::rand
std::mt19937
需要一个种子(seed),推荐用
std::random_device
初始化,避免每次运行序列相同 对
std::array
、原生数组、
std::vector
都适用,但注意传迭代器范围(
begin
/
end
) 示例(打乱 int 数组):
#include #include #include std::array arr = {1, 2, 3, 4, 5}; std::random_device rd; std::mt19937 g(rd()); // 注意:g 是 generator 对象,不是类型 std::shuffle(arr.begin(), arr.end(), g);
原生 C 风格数组怎么 shuffle?别传数组名 对
int arr[10]
这类原生数组,不能写
std::shuffle(arr, arr+10, g)
—— 这语法合法但危险:如果
arr
是函数参数(即退化为指针),
sizeof(arr)
就不是 10,
arr+10
可能越界。更稳妥的方式是封装成
std::span
(C++20)或用
std::begin
/
std::end
: 立即学习 “ C++免费学习笔记(深入) ”; C知道 CSDN推出的一款AI技术问答工具 下载 C++11/14/17:用
std::shuffle(std::begin(arr), std::end(arr), g)
,依赖 ADL 正确推导长度 若需兼容旧标准或手动控制,定义
constexpr size_t N = 10;
,再用
arr + N
绝对不要在函数内对形参数组用
sizeof
算长度 想复现某次打乱结果?固定 seed 就行 调试或测试时需要可重现的乱序,就把
std::mt19937
的种子写死,比如
std::mt19937 g(42)
。这比老式
srand(42); random_shuffle(...)
更可靠,因为
std::shuffle
的算法是确定性的 Fisher–Yates,引擎行为也完全由 seed 决定。 注意:同一个
g
对象只能用一次
shuffle
;如果反复 shuffle 同一容器,需重新构造
g
或调用
g.seed(new_seed)
,否则后续 shuffle 会基于上次剩余状态,结果仍可重现但非预期。 真正容易被忽略的是:
std::shuffle
不抛异常,但若传入无效迭代器范围(如
begin > end
),行为未定义;而
std::random_device
在某些嵌入式或受限环境可能抛
std::runtime_error
,生产环境建议加 try-catch 或 fallback 到时间种子。

相关文章