🍏对象生存期和资源管理|RAII设计思想
引出RAII
与Python不同,C++ 没有自动回收垃圾,这是在程序运行时释放堆内存和其他资源的 一个内部进程。 C++ 程序负责将所有已获取的资源返回到操作系统。 未能释放未使用的 资源称为“泄漏”。 在进程退出之前,泄漏的资源无法用于其他程序。 特别是内存泄漏是 C / C++编程中 bug 的常见原因。
新式 C++ 通过声明栈上的对象,尽可能避免使用堆内存。 当某个资源对于栈来说太 大时,则它应由对象拥有。 当该对象初始化时,它会获取它拥有的资源。 然后,该对象 负责在其析构函数中释放资源。 在栈上声明拥有资源的对象本身。 对象拥有资源的 则也称为“资源获取即初始化”(RAII)。
当拥有资源的栈对象超出范围时,会自动调用其析构函数。 这样,C++ 中的垃圾回收 与对象生存期密切相关,是确定性的。 资源始终在程序中的已知点发布,你可以控制该 点。 仅类似 C++ 中的确定析构函数可公平处理内存和非内存资源。
RAII 的好处
自动资源管理:资源的获取和释放绑定在对象的构造与析构中,减少了手动管理资源的负担。
异常安全:在异常发生时,析构函数会自动调用,确保资源得到正确释放。
简化代码:减少显式的资源管理代码,使代码更简洁、更容易维护。
提升代码可读性:资源管理逻辑清晰地嵌入到对象的生命周期中,提高代码的可读性。
一些自定义的RAII类
1. 内存管理
虽然智能指针已经很好的解决了内存管理的问题,但在一些特定的场景中,我们可能需要自定义内存管理类。
示例:自定义内存块管理类
#include <iostream>
#include <cstring>
class MemoryBlock {
public:
MemoryBlock(size_t size) {
data_ = new char[size]; // 分配内存
size_ = size;
std::cout << "MemoryBlock of size " << size << " allocated." << std::endl;
}
~MemoryBlock() {
delete[] data_; // 释放内存
std::cout << "MemoryBlock of size " << size_ << " deallocated." << std::endl;
}
// 禁止拷贝
MemoryBlock(const MemoryBlock&) = delete;
MemoryBlock& operator=(const MemoryBlock&) = delete;
// 允许移动
MemoryBlock(MemoryBlock&& other) noexcept : data_(other.data_), size_(other.size_) {
other.data_ = nullptr;
other.size_ = 0;
}
MemoryBlock& operator=(MemoryBlock&& other) noexcept {
if (this != &other) {
delete[] data_;
data_ = other.data_;
size_ = other.size_;
other.data_ = nullptr;
other.size_ = 0;
}
return *this;
}
char* data() { return data_; }
size_t size() const { return size_; }
private:
char* data_;
size_t size_;
};
int main() {
MemoryBlock block1(1024); // 分配1KB的内存块
MemoryBlock block2(2048); // 分配2KB的内存块
// 将block1的资源转移到block3
MemoryBlock block3(std::move(block1));
return 0;
}2. 线程锁管理
在多线程编程中,使用RAII管理锁可以确保在所有代码路径上都能正确释放锁,避免死锁的发生。
示例:自定义锁管理类
3. 文件描述符管理
管理文件描述符或套接字等资源,确保在所有代码路径上都能正确关闭资源。
示例:自定义文件描述符管理类
4. 网络资源管理
在网络编程中,管理套接字的生命周期,确保在所有代码路径上都能正确关闭套接字。
示例:自定义套接字管理类
5. 临时文件管理
在一些应用程序中,临时文件需要在程序结束时自动删除,使用RAII可以方便地管理这种资源。
示例:自定义临时文件管理类
通过自定义RAII类,可以大大简化资源管理的代码,提高程序的健壮性和可维护性。
reference
Last updated
Was this helpful?