其他分享
首页 > 其他分享> > Chapter 3

Chapter 3

作者:互联网

资源管理

条款 13 以对象管理资源

​ “以对象管理资源“”也被称为“资源取得时机便是初始化时机(RAII)”。

​ 在C++11中,应该使用 shared_ptrunique_ptr 来管理指针,因为C++的RAII机制会在两者的析构函数中自动 delete 掉指针。

​ 两者区别 :

​ 注意 :

*请记住 : *

1. 为防止资源泄漏,请使用RAII对象,它们在构造函数中获取资源并在析构函数中释放资源。

2. 两个被使用的 RAII classes 分别是 tr1::shared_ptrtr1::unique_ptr,前者是较佳选择,因为其 copy 行为比较直观。后置被禁止赋值。

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

​ 当你自定义 RAII 对象时,如果只是进行简单的赋值,会出现多个RAII对象管理同一资源,当这些对象调用析构函数时,这个资源将会被多次释放,产生错误。

​ 因此"当一个 RAII 对象被复制"应当 :

​ 通常我们会在 RAII classes内含一个 shared_ptr 成员变量,把原来的指针交给智能指针管理即可,如果我们有时候在资源释放时不仅仅是 delete 掉它,还要进行其他操作,比方说互斥器的解锁,那么可以使用指针的“删除器“(函数指针或函数对象)。

​ 例

class Lock{
public:
    explicit Lock(Mutex *pm) : mutexPtr(pm, unlock)//unlock为函数指针或函数对象
    {
        lock(mutexPtr.get());
    }
private:
    std::shared_ptr<Mutex> mutexPtr;
};
//使用右值引用转移unique_ptr的所有权
std::unique_ptr<Test> t_ptr1(new Test);
std::unique_ptr<Test> t_ptr1 = std::move(t_ptr1);

*请记住 : *

1. 复制 RAII 对象必须复制它所管理的资源,所以资源的 copying 行为决定 RAII 对象的 copying 行为。

2. 普遍常见的 RAII class copying 行为是 : 抑制 copying 、施行引用技术法。不过其他行为也可能被实现,例如深度拷贝和所有权转移。

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

​ 当你需要使用 C APIs 的时候,RAII 对象往往需要向用户提供原始资源(即所管理的指针)。

​ 有两种方式 :

class Font{
public:
    //显式转换
    FontPtr get()
    {
        return f;
    }
    
    //隐式转换
    operator FontPtr() const
    {
        return f;
    }
private:
    FontPtr f;
}
void changeFontSize(FontPtr f, int newSize);

//.c
Font f;
changeFontSize(f,10);//隐式转换,调用f.operator FontPtr()
changeFontSize(f.get(),20);//显式转换

​ 虽然这样做容易带来资源泄漏的问题,但当你确实需要的时候也是可以这样做的。

*请记住 : *

1. APIs 往往要求访问原始资源,所以每一个 RAII class 应该提供一个“取得其所管理的资源”的方法。

2. 对原始资源的访问可能经由显式转换或隐式转换,一般而言显式转换比较安全,但隐式转换对客户比较方便。

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

​ 规则 :

  1. 调用 new 时使用 [],对应的调用 delete 时也要使用 []。
  2. 最好不要对数组形式做 typedefusing之类的动作。

*请记住 : *

1. 如果你在 new 表达式中使用 [] ,必须在相应的 delete 表达式中也是用 []。如果你在 new 表达式中不使用 [],一定不要在 delete 中使用 []。

条款 17 以独立语句将 newd 对象置入智能指针

​ 举个例子 :

int priority();
void processWidget(std::shared_ptr<Widget> pw, int priority);

//调用
processWidget(std::shared_ptr<Widget>(new Widget),priority());

调用 processWidge() 时其参数内的语句执行顺序弹性很大,没有确定的执行顺序。

假设 :

  1. 执行 new Widget
  2. 调用 priority()
  3. 调用 shared_ptr 构造函数

若第二步抛出异常,指针将会遗失,导致资源泄漏。

**解决方法 : **使用分离语句。

std::shared_ptr<Widget> pw(new Widget);
processWidget(pw,priority());

*请记住 : *

1. 以独立语句将 newd 对象存储于智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄漏。

标签:Chapter,RAII,shared,unique,ptr,资源,指针
来源: https://www.cnblogs.com/Lingh/p/16618437.html