面试题答案
一键面试思路
- 理解移动语义:移动构造函数的目的是从源对象“窃取”资源,而不是复制。
std::move
用于将左值转换为右值,允许我们进行资源的“移动”操作。 - 资源管理:对于复杂类层次结构中涉及的资源,如动态分配的内存、文件句柄等,在移动构造函数中,源对象的资源应该被转移到新对象,并且源对象应处于一个可析构的安全状态(通常是资源被清空)。
- 性能与可读性平衡:使用
std::move
时,应确保代码逻辑清晰,避免过度复杂的表达式。对于每个需要移动的成员变量,使用std::move
进行移动操作。
关键代码片段
class ComplexResource {
public:
// 假设这里有动态分配的内存作为资源
int* data;
int size;
ComplexResource(int s) : size(s) {
data = new int[s];
// 初始化数据
for (int i = 0; i < s; ++i) {
data[i] = i;
}
}
// 移动构造函数
ComplexResource(ComplexResource&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
// 析构函数
~ComplexResource() {
delete[] data;
}
};
class OuterClass {
public:
ComplexResource res;
int otherData;
OuterClass(int s, int value) : res(s), otherData(value) {}
// 移动构造函数
OuterClass(OuterClass&& other) noexcept : res(std::move(other.res)), otherData(other.otherData) {
other.otherData = 0;
}
};
在上述代码中,ComplexResource
类的移动构造函数将源对象的 data
指针和 size
直接接管,并将源对象的 data
设为 nullptr
,size
设为 0
。OuterClass
的移动构造函数使用 std::move
移动其成员 res
,并直接接管 otherData
,同时将源对象的 otherData
清零,保证源对象处于可析构的安全状态。这样既实现了较好的性能(避免了不必要的复制),又保持了较高的可读性。