面试题答案
一键面试设计思路
- RAII(Resource Acquisition Is Initialization)机制:在构造函数中获取资源,在析构函数中释放资源,确保资源在对象生命周期结束时能被正确释放。
- 异常规范:在C++ 11及之后,异常规范主要通过
noexcept
关键字来表示函数是否抛出异常。这里我们要保证函数可能抛出异常。 - 强异常安全保证:意味着如果函数抛出异常,程序状态应保持不变,即所有资源应保持获取前的状态,没有任何资源泄漏。
代码示例
#include <iostream>
#include <stdexcept>
class ResourceHolder {
private:
// 模拟资源,这里用文件句柄的整数表示
int fileHandle;
public:
ResourceHolder() : fileHandle(-1) {}
// 构造函数获取资源
ResourceHolder(const std::string& filePath) {
// 这里模拟打开文件获取文件句柄
fileHandle = openFile(filePath);
if (fileHandle == -1) {
throw std::runtime_error("Failed to open file");
}
}
// 析构函数释放资源
~ResourceHolder() {
if (fileHandle != -1) {
closeFile(fileHandle);
}
}
// 禁止拷贝构造和赋值运算符
ResourceHolder(const ResourceHolder&) = delete;
ResourceHolder& operator=(const ResourceHolder&) = delete;
// 实现移动构造和移动赋值
ResourceHolder(ResourceHolder&& other) noexcept {
fileHandle = other.fileHandle;
other.fileHandle = -1;
}
ResourceHolder& operator=(ResourceHolder&& other) noexcept {
if (this != &other) {
if (fileHandle != -1) {
closeFile(fileHandle);
}
fileHandle = other.fileHandle;
other.fileHandle = -1;
}
return *this;
}
// 模拟打开文件的函数
int openFile(const std::string& filePath) {
// 实际实现应使用系统调用,这里简单返回一个模拟值
if (filePath.empty()) {
return -1;
}
return 1;
}
// 模拟关闭文件的函数
void closeFile(int handle) {
// 实际实现应使用系统调用
std::cout << "Closing file with handle: " << handle << std::endl;
}
// 实现遵循异常规范且保证强异常安全保证的成员函数
void performOperation(const std::string& newFilePath) {
ResourceHolder temp(newFilePath); // 创建临时对象来获取新资源,如果获取失败会抛出异常
// 交换当前对象和临时对象的资源
std::swap(fileHandle, temp.fileHandle);
// 临时对象析构时会释放旧资源
}
};
int main() {
try {
ResourceHolder holder("original.txt");
holder.performOperation("new.txt");
} catch (const std::exception& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
return 0;
}
在上述代码中,performOperation
函数通过创建临时 ResourceHolder
对象获取新资源,若获取失败则抛出异常,不会影响原对象状态。若成功获取,通过 std::swap
交换资源,保证了强异常安全保证。同时,整个类遵循RAII机制管理资源。