“按块交换”指将两段等长连续子数组整体互换位置,常用std::swap_ranges(要求不重叠、等长)、std::rotate(三段循环移位)或手动memmove(仅限pod类型且需规避生命周期问题)。

什么是“按块交换”?先明确操作边界
C++ 里没有叫 block_swap 的标准函数,所谓“按块交换”通常指:把一个数组(或容器)中连续的一段子数组与另一段等长的连续子数组互换位置。不是逐个元素 swap,而是两块内存区域整体对调。
关键约束有三个:std::swap_ranges 要求两段长度相等;std::rotate 可处理不等长但需三段;手动 memmove/memcpy 则要自己保证不重叠、不越界。
用 std::swap_ranges 交换等长块(最常用)
适用于两段长度相同、地址不重叠的场景,比如把前 3 个和后 3 个元素互换:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
int arr[] = {1,2,3,4,5,6,7,8,9};
std::swap_ranges(arr, arr+3, arr+6); // [4,5,6,1,2,3,7,8,9]
-
std::swap_ranges是双向迭代器安全的,支持原生数组、std::vector、std::array - 两端不能重叠(例如
swap_ranges(a, a+2, a+1)是未定义行为) - 每个元素调用
std::swap,对自定义类型要求其swap可访问且高效 - 不涉及内存移动,纯逻辑交换,适合小对象或已构造对象
用 std::rotate 实现“循环移位式”块交换
当你要把中间一块“抽出来”插到别处(比如把 [b,c] 和前后部分变成 [a,d,b,c]),本质是三段重排,std::rotate 更自然:
// arr = {a,b,c,d,e}, 想让 [b,c] 和 [d,e] 交换 → {a,d,e,b,c}
int* p1 = arr+1; // b
int* p2 = arr+3; // d
int* p3 = arr+5; // end
std::rotate(p1, p2, p3); // 等价于 rotate_left([b,c,d,e], 2)
-
std::rotate内部通常用三次 reverse 实现,时间 O(n),空间 O(1) - 它不要求两块等长,但必须是同一容器内连续三段
- 错误常见于搞反 pivot 顺序:
rotate(first, new_first, last)中new_first必须在[first, last)内
手动 memcpy/memmove:只在确定无构造/析构且需极致性能时用
如果数组是 POD 类型(如 int、float)、你已确认两块不重叠,并且编译器没做优化,可考虑:
int tmp[100]; std::memcpy(tmp, arr+0, 3*sizeof(int)); std::memcpy(arr+0, arr+5, 3*sizeof(int)); std::memcpy(arr+5, tmp, 3*sizeof(int));
- 绝对禁止对含非 trivial 构造/析构的对象(如
std::string)用memcpy—— 会跳过生命周期管理,引发崩溃或泄漏 - 重叠内存必须用
memmove,不是memcpy - 现代编译器对
std::swap_ranges常做向量化优化,手写未必更快,反而易错
真正容易被忽略的是:块交换是否需要保持相对顺序?比如交换两段字符串时,若其中一段含 '\0',用 memmove 没问题,但用 std::swap_ranges 就得确保迭代器能跨过它 —— 这取决于你怎么定义“块”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










