用std::swap交换行指针可实现o(1)行交换;只需确保arr[i]和arr[j]已合法分配,交换后arri访问的是原第j行内存。

用 std::swap 直接交换行指针(适用于动态分配的二维数组)
如果你用的是 new int*[rows] + 每行 new int[cols] 这种「指针数组」方式,那么每行本质是一个独立的 int*。交换两行只需交换对应指针,时间复杂度 O(1)。
常见错误是试图用 memcpy 或循环赋值去拷贝整行数据——完全没必要,还容易越界或漏掉指针更新。
- 确保
rows足够大,且arr[i]和arr[j]都已合法分配 - 交换后,原第 i 行的数据现在由
arr[j]指向,反之亦然 - 别忘了后续访问仍通过
arr[i][k],但此时它指向的是原来第 j 行的内存
int** arr = new int*[3]; for (int i = 0; i <h3>用 <code>std::swap</code> 逐列交换(适用于静态数组或 <code>std::array</code>)</h3><p>对于栈上声明的 <code>int arr[5][10]</code> 或 <code>std::array<:array>, 5></:array></code>,不能交换“行指针”(因为没有指针),必须交换每列元素。这时 <code>std::swap</code> 仍是最安全选择,编译器通常能优化成 <code>mov</code> 指令序列。</p><p>别手写 for 循环加临时变量:易错、难读、不通用;也别用 <code>std::memcpy</code> —— 若类型含非平凡构造函数(如 <code>std::string</code>),会跳过构造/析构,引发未定义行为。</p>
- 对
int arr[N][M],用std::swap_ranges(arr[i], arr[i] + M, arr[j]) - 对
std::array<:array m>, N></:array>,直接std::swap(mat[i], mat[j]) - 注意:
std::swap_ranges要求目标区间足够长,否则 UB
int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
std::swap_ranges(arr[0], arr[0] + 4, arr[2]); // 交换第0行和第2行
用 std::vector<:vector>></:vector> 时直接 swap 行对象
这是最推荐的现代写法:std::vector 的每一行本身就是独立对象,std::swap 会高效交换其内部指针,不复制元素。
常见误区是调用 vec[i].swap(vec[j]) —— 这是在交换两个 vector 的内容,但逻辑上你只想换“哪一行在哪个位置”,所以应该 swap 外层数组的元素,即 std::swap(vec[i], vec[j])。
- 确保
i和j在[0, vec.size())范围内,否则触发未定义行为 - swap 后,
vec[i].data()指向原vec[j]的堆内存,反之亦然 - 如果 vector 存储的是非 trivial 类型(如
std::string),依然安全
std::vector<:vector>> mat = {{1,2}, {3,4}, {5,6}};
std::swap(mat[0], mat[2]); // 安全、简洁、零拷贝</:vector>
为什么不用 std::memcpy 或手写循环?
除非你明确控制内存布局且类型是 POD(如纯 int 数组),否则 memcpy 极易出问题:遇到 std::string、std::vector 或带虚函数的类时,会破坏对象内部状态。
手写循环看似可控,但容易漏掉边界检查、写错索引方向(比如把 j 写成 i)、或忘记处理 move 语义导致深拷贝性能暴跌。
- 所有标准容器和内置数组都支持
std::swap的特化,优先用它 - 自定义类型若需支持行交换,请提供移动构造/赋值或特化
std::swap - 调试时若发现某行数据“变空”或“重复”,大概率是用了
memcpy或 swap 了错误的对象层级
交换的本质不是“搬数据”,而是“改引用关系”。选哪种方式,取决于你的二维结构底层是什么——指针数组?栈数组?还是 vector 嵌套。搞错这一层,后面所有操作都会偏移。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











