std::rotate是唯一专为重叠内存循环位移设计的标准算法,内部用三次反转实现,支持trivially copyable和可移动类型,时间O(n)、空间O(1),参数需满足first≤middle≤last且middle≠last。

直接用 std::rotate,别手写循环、别乱套 std::move、更别用 std::copy 处理重叠区间——它是标准库中唯一专为这事设计、且不产生额外对象拷贝的算法。
为什么 std::rotate 是唯一靠谱选择
数组区间移动(比如把 [i, j) 挪到末尾)本质是重叠内存的循环位移。手写 for 循环容易越界、破坏缓存局部性;std::move 只转换单个对象为右值引用,根本不动内存位置;std::copy 在源目标重叠时行为未定义,加 std::make_move_iterator 也救不回来——标准明确禁止。
-
std::rotate内部用三次反转实现,天然支持重叠,时间复杂度O(n),空间O(1) - 对
trivially copyable类型(如int、float、POD struct),编译器通常内联为memmove - 对可移动类型(如
std::string、std::unique_ptr),自动调用移动构造/赋值,前提是类真有T(T&&)且没被=delete
std::rotate 的参数怎么填才不出错
它的三个迭代器参数不是“左移 k 位”,而是指定两段切割点:[first, middle) 和 [middle, last) 交换位置。填错顺序或越界,行为未定义(不报错,但可能崩溃或静默错乱)。
- 把前
k个元素移到末尾(左旋):std::rotate(v.begin(), v.begin() + k, v.end()) - 把后
k个元素移到开头(右旋):std::rotate(v.begin(), v.end() - k, v.end()),必须先k %= v.size() - 对裸数组:
std::rotate(arr, arr + offset, arr + size),arr + size必须是合法末尾地址 - 边界硬约束:
first ≤ middle ≤ last;middle == last是未定义行为
自定义类型移动失效?三件事立刻检查
表面调了 std::rotate,实则还在深拷贝,性能暴跌。这不是算法问题,是类型没配好。
立即学习“C++免费学习笔记(深入)”;
- 类必须声明非删除的移动构造函数:
T(T&&) noexcept(noexcept很关键,否则某些 STL 实现会回避移动) - 所有成员变量也得支持移动(例如含裸指针的类需手动写移动逻辑,
std::vector成员默认支持) - 确认是否真走移动路径:在移动构造函数里打日志,或用断点观察调用栈——别信“看起来像”
什么情况下该放弃 std::rotate,改用 memmove
仅当同时满足这三个条件时,memmove 才是更优解:
- 目标是裸数组(非容器),比如
int buf[1024] - 元素类型是
trivially copyable(可用static_assert(std::is_trivially_copyable_v<t>)</t>验证) - 你明确知道跳过析构/构造是安全的(比如纯数据结构,无资源管理语义)
其他情况——尤其是含析构函数的类型、或不确定是否 trivial——直接用 std::rotate。它内部已做类型分发,比手写 memcpy 或 memmove 更安全、更通用。


















