Effective C++: 以对象管理资源
Using objects to manage resources
views
| comments
这是 Effective C++ 的第 13 个条款,Using objects to manage resources,中文翻译为:以对象管理资源。
在 C++ 中,资源通常指哪些一旦用了它,将来就必须还回去的东西,比如文件句柄、网络连接、互斥锁、动态分配的内存等。以动态分配内存为例,使用 new
分配的内存必须用 delete
释放,否则就会发生内存泄漏。
在书中,作者举了这样一个例子:
// 一个生产 Investment 对象的工厂函数
Investment* createInvestment();
void f()
{
Investment* pInv = createInvestment(); // 调用工厂函数,获得资源
... // 其他操作
delete pInv; // 手动释放资源
}
cpp这段代码的问题在于,如果中间的...
部分发生了异常,或者函数有多个 return
路径、continue
或 goto
语句提前退出,那么 delete pInv
就可能永远不会被执行,从而导致资源泄漏(在这个例子中是内存泄漏)。手动管理资源是不可靠且危险的。
为了解决这个问题,C++ 提供了一种更安全的资源管理方式:资源获取即初始化(RAII, Resource Acquisition Is Initialization)。RAII 的核心思想是将资源的获取和释放绑定到对象的生命周期上。具体做法是:
- 在构造函数中获取资源:将资源(如动态分配的内存指针)封装在一个类中,在类的构造函数里完成资源的申请。
- 在析构函数中释放资源:在类的析构函数里执行资源的释放操作(如 delete)。
由于 C++ 语言保证,当一个对象离开其作用域时(无论是函数正常结束还是因为抛出异常),它的析构函数一定会被自动调用。这样一来,资源的释放就变成了自动行为,永远不会被遗漏。
在现代 C++ 中,标准库提供了许多 RAII 风格的类来管理各种资源。例如:
std::unique_ptr
和std::shared_ptr
:用于管理动态分配的内存。std::lock_guard
和std::unique_lock
:用于管理互斥锁。std::fstream
:用于管理文件句柄。
通过使用这些 RAII 类,我们可以大大简化资源管理的代码,减少错误发生的可能性。