Effective C++:3.资源管理

所谓资源,就是一旦用了,就要还给系统。C++中最常见的就是动态分配内存。其他资源还包括文件描述符、互斥锁等等

1.条款13:以对象管理资源

把资源放到对象内,那么就可以通过C++的析构函数自动调用的机制去确保资源被释放。这种观念常被称为RAII(资源取得时机就是初始化时机)
智能指针shared_ptr就是这种思想的实现:

std::shared_ptr<Cat> cat;

以上的代码声明了一个Cat类型的共享指针,shared_ptr会确保Cat的销毁
总结: 把资源放到对象内,那么就可以通过C++的析构函数自动调用的机制去确保资源被释放。,而shared_ptr则是这种想法的一个优雅的实现

2.条款14:在资源管理类中小心copying行为

RAII对象必须一并复制它所管理的类,所以资源的copying行为决定RAII对象的copying行为。RAII对象的复制我们一般有两种需求:

  • 禁止复制,可以参照条款6实现,或者参照 C++11,声明delete显式删除拷贝构造函数
  • 希望底层资源能够在最后一个使用者不使用后才删除:施行指针计数法,把资源声明为shared_ptr
    总结:
  • 复制RAII对象必须复制它的所有资源,所以资源的copying行为决定RAII对象的copying行为
  • 普遍而常见的RAII拷贝行为是抑制拷贝、施行指针计数法

3.条款15:在资源管理类中提供对原始资源的访问

API往往要求访问原始资源,所以每一个RAII类应该提供一个取得原始资源的,主要有了两种方式:

  • 显式转换
    1. 在shared_ptr内可以利用get函数显式获取资源

std::shared_ptr<Cat> cat;
cat.get()                //显式获取资源
  2. 在自己实现类中则是
FontHandle getFont()     //这是C语言的API函数
class Font{
public:
  FontHandle get() const{return f;}
private:
  FontHandle f;
}
  • 隐式转换:
FontHandle getFont()     //这是C语言的API函数
class Font{
public:
  operator FontHandle() const{return f;}
private:
  FontHandle f;
}

显式转换比较安全,隐式转换比较方便。
总结:

  • API往往要求访问原始资源,所以每一个RAII类应该提供一个取得原始资源的,主要有了两种方法,显式转换和隐式转换,显式转换比较安全,隐式转换方便用户。

4.条款16:成对使用new和delete时要采取相同形式

C++ new和delete 有两种形式

  1. new或者delete一个对象
string * hello= new string("hello");
delete hello;
  1. new或者delete一个对象组成的数组
string * hellos = new string[100]
delete hellos [];

如果对上述两种形式混用,会出现错误,因需要匹配使用。
总结: C++ new和delte 有两种形式:new或者delete一个对象,new或者delete一个对象组成的数组。需要搭配使用

5.以独立语句将newed对象置入智能指针

在使用只能指针的时候需要使用独立的语句子将newed对象置入智能指针。比如有如下的函数

int eat();
void dailyLife(shared_ptr<Cat> cat , int eaten);

用户可能会这样调用函数:

dailyLife(shared_ptr<Cat>(new Cat), eat());

C++此时需要执行:

  1. Cat构造
  2. shared_ptr构造
  3. eat函数调用
    而在C++下,这三个函数的先后顺序不一定,如果顺序是下面这样:
  4. Cat构造
  5. eat函数调用
  6. shared_ptr构造
    则会发生问题:如果eat调用函数发生异常,那么Cat构造返回的指针将会丢,因为此时Cat指针尚未被shared_ptr管理起来
    因此正确的在做法是以独立语句将newed对象置入智能指针:
shared_ptr<Cat> cat (new Cat); 
dailyLife(cat, eat());

总结: 以独立语句将newed对象置入智能指针

posted @ 2024-05-19 16:54  zlj_shell  阅读(22)  评论(0)    收藏  举报