Effective-cpp-#13

Use objects to manage resources

动机

内存管理在C++中是非常重要而且常见的,往往会因为管理不当而出现灾难性的内存泄漏情况。首先来看一个例子:

1
2
3
4
5
6
7
8
9
class Investment;
Investment* createInvestment();

void f()
{
Investment* pInv = createInvestment();
...
delete pInv;
}

在上面的例子中,乍一看很好地管理分配的资源,但闻题在...这里,如果在delete之前函数提前返回,或者发生了异常被抛出来,那么就会导致delete语句没有被访问到,也就是发生了内存泄漏的情况。

解决方法

因此为了确保createInvestment()分配的资源被正确释放,可以把资源放到对象中进行管理,从而控制其在离开区块时因为调用析构函数而释放资源。

  • auto_ptr
    • auto_ptr是一个智能指针,该指针管理的对象在析构函数时会调用delete;
    • 这是一种RAII的使用方法,即获得资源的第一时间则将其用来初始化某个对象;
    • 但这个智能指针有两个特点:
      • 会转移控制权,若通过copy构造函数或者copy赋值函数取赋值该指针,原指针会指向一个null;
      • 不能有多个auto_ptr指向同一个对象,因为这样容易导致多次delete或者未定义行为;
1
2
3
4
5
void f()
{
std::auto_ptr<Investment> pInv(createInvestment());
std::auto_ptr<Investment> pInv1(pInv);//pInv指向null
}
  • share_ptr
    • 这类智能指针允许对象被多个指针指向,并维持一个引用计数,具体使用参考:http://www.lucienxian.top/2017/11/16/%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E7%9A%84%E5%AD%A6%E4%B9%A0%E2%80%94%E2%80%94CPP/

建议

  • 为防止资源泄漏,应使用RAII对象,在构造函数中获得资源,在析构函数中释放资源;
  • 两个常用的RAII类是:auto_ptr和shared_ptr;