面试题答案
一键面试设计思路
- 资源管理:使用RAII(Resource Acquisition Is Initialization)原则来管理数据库连接资源。在构造函数中获取资源(如打开数据库连接并获取句柄),在析构函数中释放资源(如关闭数据库连接)。
- 拷贝构造函数:实现深拷贝,确保每个对象都有自己独立的资源。当拷贝对象时,创建一个新的数据库连接句柄,而不是共享原对象的句柄。
- 异常安全性:在构造和拷贝过程中,确保在任何异常情况下资源都能正确释放。使用try - catch块捕获可能抛出的异常,并在异常发生时清理已获取的资源。
代码实现(以C++为例)
#include <iostream>
#include <stdexcept>
class DatabaseConnection {
private:
// 假设这是数据库连接句柄
void* connectionHandle;
public:
// 构造函数
DatabaseConnection() {
// 模拟获取数据库连接
connectionHandle = nullptr;
try {
// 这里可能是实际获取连接的操作,例如调用数据库API
connectionHandle = reinterpret_cast<void*>(new char[1]);
} catch (const std::bad_alloc& e) {
std::cerr << "Failed to allocate memory for connection handle: " << e.what() << std::endl;
// 这里可以进行更具体的资源清理,由于模拟简单,暂不做更多处理
throw;
}
}
// 拷贝构造函数
DatabaseConnection(const DatabaseConnection& other) {
// 模拟深拷贝,创建新的数据库连接
connectionHandle = nullptr;
try {
// 这里可能是实际获取连接的操作,例如调用数据库API
connectionHandle = reinterpret_cast<void*>(new char[1]);
} catch (const std::bad_alloc& e) {
std::cerr << "Failed to allocate memory for connection handle in copy constructor: " << e.what() << std::endl;
// 这里可以进行更具体的资源清理,由于模拟简单,暂不做更多处理
throw;
}
}
// 析构函数
~DatabaseConnection() {
// 模拟释放数据库连接
if (connectionHandle != nullptr) {
delete[] reinterpret_cast<char*>(connectionHandle);
connectionHandle = nullptr;
}
}
// 赋值运算符重载(为了代码完整性,这里简单实现,实际应用中可能更复杂)
DatabaseConnection& operator=(const DatabaseConnection& other) {
if (this != &other) {
// 释放当前资源
if (connectionHandle != nullptr) {
delete[] reinterpret_cast<char*>(connectionHandle);
}
// 深拷贝资源
try {
connectionHandle = reinterpret_cast<void*>(new char[1]);
} catch (const std::bad_alloc& e) {
std::cerr << "Failed to allocate memory in assignment operator: " << e.what() << std::endl;
// 这里可以进行更具体的资源清理,由于模拟简单,暂不做更多处理
throw;
}
}
return *this;
}
};
以上代码通过RAII管理数据库连接资源,在构造、拷贝构造和赋值运算符重载中都考虑了异常安全性,确保在任何异常情况下资源都不会泄露且对象处于有效状态。实际应用中,connectionHandle
应该是真实的数据库连接句柄,获取和释放连接的操作应替换为实际的数据库API调用。