在C++11之后,移动语义成为提升程序性能的重要工具。当我们在容器中交换两个重量级对象时,传统的拷贝方式会分配和释放内存,造成浪费。借助移动语义,只需转移内部指针等资源,就能完成交换。下面通过示例说明具体做法。

为什么普通交换效率低
假设容器里放的是含有动态数组的类,使用std::swap进行交换会触发拷贝构造和赋值,导致多次内存分配。移动语义允许我们“偷”走对方资源,避免这些开销。
为类定义移动构造与移动赋值
要让自定义类型支持高效交换,需要先实现移动构造函数和移动赋值运算符,并使用noexcept标记,这样标准库容器在扩容或排序时才会使用移动而非拷贝。
#include <iostream>
#include <vector>
#include <utility>
class Buffer {
public:
int* data;
size_t size;
Buffer(size_t n) : size(n), data(new int[n]) {}
// 移动构造函数
Buffer(Buffer&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
// 移动赋值
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
~Buffer() { delete[] data; }
};
int main() {
std::vector<Buffer> vec;
vec.emplace_back(10);
vec.emplace_back(20);
// 使用移动语义交换元素
std::swap(vec[0], vec[1]);
return 0;
}
利用std::move显式优化
有时我们需要把容器元素移到临时位置再处理,可以调用std::move触发移动而非拷贝。
#include <vector>
#include <utility>
int main() {
std::vector<int> a = {1, 2, 3};
std::vector<int> b;
b = std::move(a); // 移动而非拷贝,a变为空
return 0;
}
注意事项
- 移动后原对象处于有效但未指定状态,不要再用其值。
- 标记noexcept能帮助容器选择移动路径。
- 标准容器如vector本身已支持移动,直接交换容器也很高效。
合理使用移动语义,可以让容器元素交换从昂贵的深拷贝变成廉价的指针交接,对性能敏感的场景尤为重要。