std::rotate是专为连续内存区间循环移位设计的唯一标准算法,通过三次反转实现O(n)时间、O(1)空间的原地操作,将[first, middle)与[middle, last)两段交换位置。

std::rotate 是最直接的解法
对连续内存(如 std::vector、原生数组)做区间移动,std::rotate 是标准库中唯一专为此设计、且不产生额外元素拷贝的算法。它把迭代器范围 [first, middle) 和 [middle, last) 两段交换位置,等价于“把 middle 开始的部分移到前面”,本质是三次反转,时间复杂度 O(n),空间复杂度 O(1)。
常见误用是试图用 std::copy + std::move 手动搬移 —— 这不仅容易越界,还可能触发多次构造/析构;而 std::rotate 内部已针对 POD 和可移动类型做了优化路径。
- 若想把后 k 个元素移到开头:
std::rotate(v.begin(), v.end() - k, v.end()) - 若想把前 k 个元素移到末尾:
std::rotate(v.begin(), v.begin() + k, v.end()) - 对原生数组需传入指针:
std::rotate(arr, arr + offset, arr + size)
move_iterator 配合 std::copy 只适用于“右移且留空位”场景
当目标区间与源区间不重叠(比如把 [0, n) 搬到 [m, m+n),且 m > n),可用 std::copy + std::make_move_iterator 避免深拷贝。但它不是“区间移动”的通用解,一旦源目标重叠,行为未定义 —— 这点极易被忽略。
典型错误:用 std::copy(std::make_move_iterator(src), ..., dst) 去覆盖自身前方内存,结果部分元素被提前移动或析构,后续读取失效。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 安全前提:dst 起始地址 ≥ src + n,或 dst + n ≤ src
- 否则必须用
std::rotate或手动分段处理 -
std::move_backward适合“左移重叠”,但仅限尾部重叠,且要求类型支持移动赋值
自定义类型要注意移动语义是否真正生效
std::rotate 在内部会根据类型是否为 std::is_trivially_move_constructible_v<T> 等特性选择 memcpy 路径或逐个调用移动构造函数。如果自定义类没声明移动操作,或移动构造函数被删除/未定义,就会退化为拷贝 —— 表面没报错,实则性能暴跌。
- 检查方式:加断点或打印构造/析构日志,确认调用的是移动而非拷贝
- 确保类有
T(T&&)且未被 =delete,且成员变量都支持移动 - POD 类型(如
struct {int x; float y;})天然走 memcpy,最快
原生数组 + memmove 是最后的保底手段
当编译器版本老旧(如 C++11 之前)、或使用裸数组且确定元素是 POD,memmove 是最轻量、最可控的选择。它明确处理重叠内存,比手写循环更可靠,也比 std::rotate 少一层泛型开销。
注意:memcpy 不行 —— 它不保证重叠内存安全;memmove 可以,但只适用于 trivial 类型。
- 移动后 k 个到开头:
memmove(arr, arr + size - k, k * sizeof(T)) - 移动前 k 个到末尾:
memmove(arr + k, arr, (size - k) * sizeof(T)) - 务必确认
T是 trivially copyable,否则行为未定义
真正难的不是选哪个函数,而是判断移动方向、重叠关系和类型属性 —— 这三者错一个,std::rotate 也可能悄悄变慢,memmove 可能直接崩溃。

















